我得到了意想不到的结果,至今我都无法解释自己。C++协方差意外行为
虽然生成了两次同一类BASIC2
(继承自BASIC1
)的对象,但在生成的对象上使用好友operator<<
时会生成不同的消息。下面
查看代码,我让D
(一类Derived
从Base
继承的对象)产生BASIC2
类的一个对象,并调用它的朋友operator<<
。这产生了预期的消息"BASIC2 object"
。
我让B
生成类BASIC1
的一个对象,并将其称为其朋友operator<<
。如我所料,这输出"BASIC1 object"
。
然后我用虚拟继承让B2
(Base* B2 = &D;
)生成一个对象BASIC2
。我遵循调试器(Visual Studio 2010)中的代码流,这会正确生成BASIC2
的对象。但是,朋友operator<<
未在BASIC2
对象上调用,但使用类BASIC1
的朋友operator<<
(因此输出"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:
};
那么'B2'的静态类型是'Base',所以编译器看到的函数是'BASIC1 * Base :: generate(double)'(动态调度调用'Derived :: generate')。不过,返回类型是'BASIC1 *'。并且基于表达式*(B2-> generate(0))'的静态类型选择'operator <<'。 – dyp
@dyp:I.e.这个'operator <<'不是''virtual'“。 –
运行时/动态分派只在成员函数中完成。 – molbdnilo