我得到了一个意想不到的结果,到目前为止我无法解释自己。
虽然两次都是同一个类的对象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"
)。
另请注意,我确实想要 BASIC2
从 BASIC1
继承因为我想利用协方差行为。
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/