我得到了意想不到的結果,至今我都無法解釋自己。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