代码之家  ›  专栏  ›  技术社区  ›  Marine Galantin

C++中的学习案例。抽象类和实例[关闭]

  •  -2
  • Marine Galantin  · 技术社区  · 7 年前

    我必须理解为什么C++中的程序不起作用。还有许多其他错误,但我改正了。

    #include <iostream>
    using namespace std;
    
    class X {
        public : 
        X(int a) : a(a) {}
        virtual void f(ostream& flot) const { flot << " X::f" << endl; }
        virtual void g() const = 0;
    
        private :
        int a;
    };
    
    
    class Z : public X {
        void h() const {cout << "Z::h" << endl;}
        public :
        Z() : X(0) {}
        void f(ostream& flot) const override { flot << "Z::f" << endl;}
        void g() const override  {cout << "Z::g" << endl;} 
    };
    
    void operator<< (ostream& flot, const Z& z ) { z.f(flot);}
    
    
    
    int main() {
        Z z;
        cout << z << endl;
        Z z2();
        z2.h();
        X* x1;
        x1->f(cout);
        z.h();
    
    }
    

    您不能写入cout<<z<<endl;,因为z不作为普通对象存在,是正确的吗?它是一种虚构的物体?与Z2相反,Z2的构造和存在。你能告诉我我是否是对的吗?

    我不明白为什么最后两行:

    x1->f(cout);
    z.h();
    

    没有问题。我认为x1不存在(如z)。那么,为什么可以为x1调用一个方法呢?

    对于z.h(),唯一的问题是h在这里,在这个上下文中,是私有的。但如果它是在公共领域,那就不是问题了。为什么????Z不是虚构的,所以你不能在上面使用任何方法吗?

    3 回复  |  直到 7 年前
        1
  •  2
  •   dascandy    7 年前
    Z z;
    

    它定义和构造一个对象 z 类型 Z . 将调用默认构造函数。

    cout << z << endl;
    

    这个电话 operator<< 对于 (cout, z) ,然后使用该函数的返回值调用 操作员<< 为了它和 endl . 返回值为空,因此第二个调用无法工作。你的 操作员<< 需要返回输出流才能使其工作。

    Z z2();
    

    这定义了一个函数 z2 不接受参数并返回 Z . 不是一个变量,但实际上它本身没有错。

    z2.h();
    

    在这一点上是错误的,因为 Z2 是函数而不是对象。尝试删除括号,或将前一行改为 Z z2 = Z(); .

    X* x1;
    

    这定义了一个变量 x1 类型 X* . 它未初始化。

    x1->f(cout);
    

    这将调用函数 X::f 在未初始化的指针上,这是未定义的行为。将未定义的行为理解为“可以做任何事情,避免”。

    z.h();
    

    这将尝试调用函数 h Z 但它是一个私人功能。您将得到一个编译错误,因为它是私有的,无法从 main 上下文。

        2
  •  1
  •   Jorge    7 年前

    得到 cout 接受 Z 对象在运算符之后 << ,超载操作员 << 识别 ostream 左侧的对象和 Z 在右边。超载 << 然后必须将运算符函数声明为类的友元 Z .

    第一个错误是通过向z类添加以下声明来解决的:

    friend ostream& operator<<(ostream& os, const Z& z);
    

    另一方面,如果要调用该方法 h 在实例上 z2 你必须做 H 公共方法,在代码中是 private 默认情况下。

    最后一点,您应该在句子中收到一个分段错误:

    x1->f(cout);
    

    因为指针x1指向一个未分配的对象。

        3
  •  1
  •   mahesh    7 年前

    C++中没有虚构的对象。对象已创建或未创建。什么都没有 Z z; . 因为对象存在,所以在使用函数时没有问题 Z::h() 一旦你成功了 public .

    Z z2(); 不按您的意愿创建对象,因为它被解析为不带参数并返回的对象的函数。 Z . 正如第一条评论中指出的,这是最麻烦的解析。

    关于 cout ,接线员 << 应该能够打印你班上的东西。因此,你需要让接线员成为你班的朋友。

    还有,因为 x1 已声明但未初始化,您将具有未定义的行为 x1->f(); . 而且,你甚至不能做这样的事 X* x1 = new X(0); 因为 X::g() 是纯虚拟的,类 X 是抽象基类。

    以下代码运行时不会出现问题:

    #include <iostream>
    using namespace std;
    
    class X {
        public :
        X(int a) : a(a) {}
        virtual ~X() {}
        virtual void f(ostream& flot) const { flot << " X::f" << endl; }
        virtual void g() const {};
    
        private :
        int a;
    };
    
    
    class Z : public X {
        public :
        Z() : X(0) {}
        void f(ostream& flot) const override { flot << "Z::f" << endl;}
        void g() const override  {cout << "Z::g" << endl;}
        void h() const {cout << "Z::h" << endl;}
        friend ostream &operator<<(ostream &os, const Z &z);
    };
    
    ostream& operator<< (ostream& flot, const Z& z ) { z.f(flot); return flot;}
    
    int main() {
        Z z;
        cout << z << endl;
        //Z z2();
        //z2.h();
        X * x1 = new X(0);
        x1->f(cout);
        z.h();
        delete x1;
        return 0;
    }