-2

我必须理解为什么这个 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 相反。你能告诉我我是否正确吗?

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

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

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

而对于 zh(),唯一的问题是 h 在此上下文中是私有的。但如果它在公共部分内部,那将不是问题。为什么 ???z不是虚构的,所以你不能对它使用任何方法吗?

4

3 回答 3

2
Z z;

这定义并构造了一个z类型为 的对象Z。调用默认构造函数。

cout << z << endl;

这调用operator<<(cout, z)然后使用它的返回值调用operator<<它和endl。返回值为 void,因此第二次调用无法工作。您operator<<需要返回输出流才能使其正常工作。

Z z2();

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

z2.h();

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

X* x1;

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

x1->f(cout);

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

z.h();

这试图调用函数hon z,但它是一个私有函数。你会得到一个编译错误,因为它是私有的并且不能从main上下文中访问。

于 2018-05-23T07:40:13.487 回答
1

要在运算符之后cout接受Z对象<<,请重载运算符<<以识别ostream左侧的对象和Z右侧的 a。<<然后必须将重载的运算符函数声明为 class 的朋友Z

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

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

另一方面,如果你想h在实例上调用方法,z2你必须创建h 公共方法,在你的代码中它是private默认的。

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

x1->f(cout);

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

于 2018-05-23T07:40:02.120 回答
1

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;
}
于 2018-05-23T08:13:59.057 回答