2013-08-12 37 views
0

假設我有這樣的代碼:友好和繼承

#include <iostream> 
using namespace std; 

class A 
{ 
protected: 
    virtual ~A() { cout << "A destructor reached." << endl;} 

    friend class Z; 
}; 

class B : public A 
{ 
protected: 
    virtual ~B() { cout << "B destructor reached." << endl; } 
}; 

class Z 
{ 
public: 
    void Test(); 

    friend class A; 
}; 

void Z::Test() 
{ 
    A* derived = (A*) new B(); 

    delete derived; 
} 

int main() 
{ 
    Z test; 
    test.Test(); 
} 

什麼事情發生,就會在B的析構函數被調用?它合法嗎?如果不是,有沒有辦法調用派生的構造函數,而不需要從Z的一個朋友派生每個類?

+0

你試過嗎? – Beta

+0

@貝塔是的,我可以,但我想確定行爲與我的編譯器(VS 2012)和標準沒有什麼關係。 – denidare

回答

1

標準,§11.5/ 1「訪問虛擬功能,說:」

爲虛擬功能的訪問規則(第11)是由它的聲明來確定,並且不受爲一個規則函數稍後會覆蓋它。

因此,只要您有權訪問A::~A,即可致電B::~B。但是您必須通過A來調用它,因爲Z無權訪問B

順便說一句,在Z中的朋友聲明是沒用的,因爲沒有任何東西是私人的或在其中受到保護。

+0

謝謝,這就是我想要的。 – denidare

1

這裏至少涉及兩個問題。

是的,B的析構函數會被調用。這就是多態性是如何工作的,這就是虛擬析構函數的工作原理,它是通過設計來實現的,這是一件好事。

事實上,一個成員函數在B中被保護(甚至是私有),但在A中是虛擬的並且可用(例如公共)可以通過A *調用,但起初可能有點奇怪,但它也是有設計的。有什麼選擇?我能看到的唯一的其他選擇是禁止繼承,這會增加虛擬成員函數的限制;這有什麼好的目的?

如果您不想讓方法可訪問,請不要從可訪問的虛擬父方法派生它。