2012-01-24 222 views
3

基於我的研究,我認爲這有一個很好的感覺,但希望得到確認。我一直在學習繼承和虛擬方法的工作方式。繼承和虛擬方法

在底部的代碼中,運行main時會得到結果(上面的代碼)。如果我將printType方法切換爲非虛擬方式,則會打印出「AbstractClass」。

據我所知,使用「虛擬」表示該方法可能被覆蓋 - 並總是選擇該方法的「最後重新實現」,在這種情況下在ImplementationClass中。我的問題是:

1)這是否總是會發生?或者是否存在這樣的情況:即使它是一種虛擬方法,您可能最終會使用AbstractClass(或其他類,如果它被多次繼承)的方法被調用?

2)似乎你不能實例化一個包含虛擬方法的類的非指針。這是真的?

3)我假設在我的兩個例子中沒有什麼不同,但我只有約80%的可信度。

非常感謝您的幫助,這整個虛擬方法的東西很難從閱讀中找出來(這就是爲什麼我首先創建了一個虛擬項目!)。

after redefinition 
ImplementationClass 
printing from virtual method in ImplementationClass 

second set of examples 
ImplementationClass 
printing from virtual method in ImplementationClass 

#include <iostream> 
using namespace std; 

class AbstractClass{ 

public: 
    virtual void printStuff() = 0; 
    AbstractClass() {}; 
    ~AbstractClass() {}; 

    virtual void printType() { std::cout << "AbstractClass" << std::endl; } 
    // void printType() { std::cout << "AbstractClass" << std::endl; } 

}; 
class ImplementationClass : public AbstractClass { 

public: 
    void printStuff() { std::cout << "printing from virtual method in ImplementationClass" << std::endl;} 
    void printType() { std::cout << "ImplementationClass" << std::endl; } 
    void printStuffOnlyInDerived() {std::cout << "printing from NONvirtual method in ImplementationClass" << std::endl;} 


    ImplementationClass() {}; 
    ~ImplementationClass() {}; 
}; 




int main() { 

    AbstractClass * absClass; 
    ImplementationClass * impClass= new ImplementationClass; 

    absClass = impClass; 

    printf("\nafter redefinition \n"); 
    absClass->printType(); 
    absClass->printStuff(); 


    AbstractClass * absClassNonPtrImpClass = new ImplementationClass; 

    printf("\n second set of examples \n"); 
    absClassNonPtrImpClass->printType(); 
    absClassNonPtrImpClass->printStuff(); 


    return 0; 
} 
+0

不,它並不總是會發生。當在基類的構造函數中調用虛函數並且該函數尚未被覆蓋時,原函數將被調用。 –

回答

1

1)這是否總是會發生?

有沒有在那裏你可以從抽象類的方法最終實例(或其它類,如果它繼承了多次)被調用,即使它是一個虛擬的方法?

是的,如果沒有在派生類中定義的,並不= 0 如果定義在派生類,您仍然可以調用基類的版本的BaseClass ::方法() ;

2)似乎你不能實例化一個包含虛擬方法的類的非指針。這是真的?

你可以實例化一個包含虛擬方法的類,但是如果它們= 0,那麼它是抽象的,你不能。

+0

哦,很酷,我什至不知道absClass-> AbstractClass :: printType();將工作 – enderland

+0

是的,::是「範圍解析運算符」。 – Foggzie

+0

@Gunther Fox:不,它並不總是會發生。當在基類的構造函數中調用虛函數並且該函數尚未被覆蓋時,原函數將被調用。 –

1

1)是的,多態性始終有效。

2)你弄錯了,你可以在自動存儲中實例化類的對象。

你不能在你的例子中的原因是因爲你的基類是抽象的。

此:

AbstractClass * absClass; 

僅聲明一個指針的基類。它不會創建實際的對象。

以下是合法的:

ImplementationClass x; 

雖然ImplementationClass是一個多態型,您可以創建在自動存儲對象(而不是你通過指針叫什麼)。你可以這樣做,因爲基類中的抽象方法是在派生類中實現的。

+0

「2)你弄錯了,你可以在自動存儲中實例化類的對象。」 啊,好的,你的第二個例子回答了我要說的話。但是,你永遠無法做AbstractClass * myAbsClass(如果AbstractClass包含一個虛擬方法?或者僅僅是我的情況,因爲我有一個純粹的虛擬方法嗎?) – enderland

+0

@enderland是...所以? - 「2)看來你不能實例化一個包含虛擬方法的類的非指針,這是真的嗎?」這是不正確的,你可以實例化包含虛擬方法的類的非指針(???)。 –

+0

@enderland'AbstractClass * myAbsClass'不會實例化一個類,它只是一個指針聲明。你可以有一個指向抽象類的指針聲明。你不能做的是創建一個實例:'AbstractClass * myAbsClass = new AbstractClass''將失敗,''AbstractClass myAbsClass;'將會失敗。 –

3
  1. 是的,你可以明確地指定基類的方法,並調用它,即使是通過指針指向一個派生類(pDerived->Base::virtualMethod() - 這將調用Base的實施virtualMethod())。你也可以使用slice派生類對象,並且也會丟失多態性。

  2. 您不能用抽象方法(用= 0聲明)創建類的對象,但您可以使用具有實現的虛擬方法創建類的對象。

+0

真棒,謝謝:)我可能錯誤地使用了「抽象」一詞。 – enderland

+0

+1我想說的。還值得一提:你可以創建指針和引用形式的抽象類。 –

+1

* to * abstract classes ... –