C 协方差意外行为

C++ covariance unexpected behaviour

本文关键字:意外 方差      更新时间:2023-10-16

我得到了意外的结果,我无法解释自己。

尽管在生成对象上使用朋友operator<<时,生成了同一类BASIC2的对象(从BASIC1继承)。

请参阅下面的代码

我让D(从Base继承的类Derived的对象)生成类BASIC2的对象,并将其称为朋友operator<<。这会产生预期消息"BASIC2 object"

我让B生成类BASIC1的对象,并致电其朋友operator<<。如我所期望的那样,这将输出"BASIC1 object"

然后,我使用虚拟继承来让B2Base* B2 = &D;)生成BASIC2的对象。我遵循调试器(Visual Studio 2010)中的代码流,这正确生成了BASIC2的对象。但是,朋友operator<<未在BASIC2对象上调用,而是使用类BASIC1的朋友operator<<(因此输出"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");
}

输出为:

基本2对象basic1对象basic1对象
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:
};

选择运算符&lt;&lt;基于在编译时间中已知对象的静态类型。为了实现您想要的目标,不要定义两个操作员&lt;&lt;功能,但仅在基本1中:

    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";
}

谢谢!对我而言,我的问题的结局是:如果您调用朋友操作员&lt;&lt;(std :: ostream&amp; os,const base&amp; object)在通过动态调度生成对象的对象上。您需要在操作员中使用虚拟功能&lt;&lt;允许动态调度操作员&lt;&lt;。