C++ 协方差意外行为

标签 c++ inheritance covariance

我得到了一个意想不到的结果,到目前为止我无法解释自己。

虽然两次都是同一个类的对象BASIC2 (继承自 BASIC1 )生成不同的消息,当使用 friend operator<< 时生成在生成的对象上。

见下面的代码

我让D (继承自 Derived 的类 Base 的对象)生成类 BASIC2 的对象并称它为 friend operator<< .这会产生预期的消息 "BASIC2 object" .

我让B生成类 BASIC1 的对象并调用它的 friend operator<< .这输出 "BASIC1 object"正如我所料。

然后我用虚继承让B2 ( Base* B2 = &D; ) 生成 BASIC2 的对象.我遵循调试器 (Visual Studio 2010) 中的代码流,这正确地生成了 BASIC2 的对象。 .不过 friend operator<<未在 BASIC2 上调用对象,但使用 friend operator<<从类 BASIC1 (因此输出 "BASIC1 object" )。

另请注意,我确实想要 BASIC2BASIC1 继承因为我想利用协方差行为。

int main(int argc, char* argv[]) {
    Base B;
    Derived D;
    Base* B2 = &D;
    std::cout << *D.generate(0) << std::endl;
    std::cout << *B.generate(0) << std::endl;
    std::cout << *(B2->generate(0)) << std::endl;
    system("pause");
}

输出是:

BASIC2 object
BASIC1 object
BASIC1 object
class BASIC1 {
public:
    friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
    os << "BASIC1 object";
    return os;
    }
};

class BASIC2 : public BASIC1 {
    friend std::ostream& operator<<(std::ostream& os, const BASIC2& basic) {
    os << "BASIC2 object";
    return os;
    }
};

class Base {
public:
    virtual BASIC1* generate(double num) const {
    return new BASIC1();
    }
protected:
private:
};

class Derived : public Base {
public:
    virtual BASIC2* generate(double num) const override {
    return new BASIC2();
    }
protected:
private:
};

最佳答案

operator<< 的选择基于编译期间已知的对象的静态类型。要实现你想要的,不要定义两个 operator<< 函数,而只在 BASIC1 中定义一个:

    friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
      Write(os);
      return os;
    }

并定义虚函数写在BASIC1和BASIC2中做你想做的:

virtual void Write(std::ostream& os) const {
   os << "BASIC1 object";
}

关于C++ 协方差意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21261971/

相关文章:

r - 如何更有效地计算滚动协方差

c++ - 了解 typeid().name() 的输出

c++ - SDL_GL_SetAttribute 不设置颜色大小

java - 方法链 + 继承不能很好地结合在一起?

haskell - 可以为这种类型创建应用实例吗?

r - 按行而不是按列用向量填充下矩阵

c++ - 我可以在 mega2560 上使用多个 DHT22 读取单独的温度/湿度吗?

c++ - 在编译时决定构造对象

c++ - 空类的单继承层次结构是否保证 sizeof 相等?

c++ - 如何使用来自不同继承层次级别的多个虚函数指针作为模板参数?