我明白,與公共繼承它一般不是安全,因爲當delete
ing一個基類指針編譯器只生成代碼來調用基類的析構函數,並且派生類的一個不被調用。使用非虛擬析構函數從類中私下繼承是否安全?
但是對於私有繼承的客戶端無法派生類指針轉換爲一個基類指針(如私有繼承不模型是,一個關係),所以delete
總是用在派生類的指針,編譯器應該能夠看到還有一個基類並調用它的析構函數。
我做了這個測試:
#include <iostream>
struct BaseVirtual
{
virtual ~BaseVirtual()
{
std::cout << "BaseVirtual's dtor" << '\n';
}
};
struct BaseNonVirtual
{
~BaseNonVirtual()
{
std::cout << "BaseNonVirtual's dtor" << '\n';
}
};
struct DerivedPrivVirtual: private BaseVirtual
{
static void f()
{
BaseVirtual * p = new DerivedPrivVirtual;
delete p;
}
~DerivedPrivVirtual()
{
std::cout << "DerivedPrivVirtual's dtor" << '\n';
}
};
struct DerivedPrivNonVirtual: private BaseNonVirtual
{
static void f()
{
BaseNonVirtual * p = new DerivedPrivNonVirtual;
delete p;
}
~DerivedPrivNonVirtual()
{
std::cout << "DerivedPrivNonVirtual's dtor" << '\n';
}
};
int main()
{
std::cout << "With explicit derived pointer type:" << '\n';
{
DerivedPrivVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
DerivedPrivNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;
delete derivedPrivVirtual;
delete derivedPrivNonVirtual;
}
std::cout << '\n';
std::cout << "With base pointer type:" << '\n';
{
// Client code can't cast Derived to Base when inherit privately.
//BaseVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
//BaseNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;
//delete derivedPrivVirtual;
//delete derivedPrivNonVirtual;
}
std::cout << '\n';
std::cout << "Inside derived class itself:" << '\n';
{
DerivedPrivVirtual::f();
DerivedPrivNonVirtual::f();
}
std::cout << '\n';
std::cout << "With non-dynamic variables:" << '\n';
{
DerivedPrivVirtual derivedPrivVirtual;
DerivedPrivNonVirtual derivedPrivNonVirtual;
}
std::cout << '\n';
}
兩個GCC 4.7.1和3.1鏗鏘給出相同的輸出。派生類的構造函數被調用,除非派生類本身將派生類指針轉換爲基類並且將其指向基類。
除了這種情況下,這種情況似乎很少見,也很容易避免(班級的作者是唯一能夠傷害的人,但它確實知道從哪個班級衍生出來),我可以得出結論:這是安全的嗎?
With explicit derived pointer type:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor
With base pointer type:
Inside derived class itself:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
BaseNonVirtual's dtor <-- Only a problem inside the class itself
With non-dynamic variables:
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor
DerivedPrivVirtual's dtor
BaseVirtual's dtor
獎金的問題:關於保護繼承什麼?我認爲造成傷害的能力不再是直接派生類作者的特權,而是階級中任何階級的作者。
如果我沒有記錯,斯科特邁爾斯(有效C++的作者,更有效的C++)仍然不知道什麼保護繼承的含義。公衆是一個「是 - 是」的關係,私人是「實施的」,但受到保護?這有點嚇人。 – Borgleader