2016-11-26 75 views
-3

我對C++中的子類有些懷疑。我有這樣的代碼:強制派生類對象使用自己的函數,而不是基類

class BaseClass() { 
    BaseClass(); 
    void doSomething(); 
} 

class SubClass : public BaseClass { 
    SubClass(); 
    void doSomething(); 
} 

當我宣佈一個BaseClass的對象可能是一個子類我做調用子構造...

BaseClass foo = SubClass(); 

然後,我需要FOO使用DoSomething的()派生類的方法,但當我這樣做...

foo.doSomething(); 

它使用父類方法,而不是派生的方法。我想這一點,但它不工作:

foo.SubClass::doSomething(); 

有沒有辦法做到這一點還是我被迫宣佈與「分類」類型的對象,以便能夠使用它自己的功能?

+1

'virtual void doSomething();'? –

+3

'BaseClass foo = SubClass();'''foo'是'BaseClass'類型的對象,而不是'SubClass'。這是**對象切片**的一個例子。並標記'doSomething()'虛擬不會改變這一點。 –

+0

是的,因爲皮特貝克說,它似乎是一個對象切片問題,所以使虛擬函數不能解決問題...解決這個問題的唯一方法是顯式聲明foo爲SubClass類型,不是嗎? – JotaEle

回答

1

問題1:對象切片

在初始化

BaseClass foo = SubClass(); 

您創建一個匿名臨時​​對象和拷貝構造BaseClass對象。這意味着foo是和仍然是從​​複製的BaseClass

這叫做object slicing。如果baseClass將具有數據成員,則將該子類的相應數據成員複製到其中。如果​​將具有其他數據成員,則這些數據將丟失。

如果你想與BaseClass對象的工作,但沒有失去其真正的類型的成員,無論是基礎或派生,你需要使用引用或指針:

BaseClass *foo = new SubClass; // foo is a base class pointer but points to a SubClass object. 

SubClass bar; 
BaseClass& foo2 = bar;   // foo2 is a base class REFERENCE which refers to a Subclass object 

但是,這是不夠的。

問題2:多態性

如果你現在想調用的方法:

foo->doSomething(); 
foo2.doSomething(); 

它仍然是BaseClass::doSomething()那被稱爲,儘管真正的類型對象的尖/簡稱至。這是因爲對於普通的成員函數,編譯器試圖在編譯時識別要調用的函數:在編譯時它只知道指針或引用的類型。

要受益於多態行爲,還需要將函數定義爲virtual,如Johan所解釋的。在這種情況下,編譯器會生成一些代碼,只需少量開銷即可動態識別對象的類型,因此可以完全按照您的預期調用正確版本的函數。

請注意,如果您的基類中至少有一個虛函數,則最好爲其聲明一個虛析構函數。

0

你可以聲明dosomeThing方法虛擬的BaseClass的,像

virtual void doSomething() 
{ 
    ---- 
} 
+0

面向對象編程的這個概念被稱爲多態性 –

2

使用虛擬和超越:

class BaseClass() { 
    BaseClass(); 
    virtual ~BaseClass() = default; 
    virtual void doSomething(); 
} 

class SubClass : public BaseClass { 
    SubClass(); 
    void doSomething() override ; 
} 

編輯:爲克里斯托夫說,如上使用虛擬析構函數。

+0

是的!但是,預見到一個虛擬的析構函數。 – Christophe

相關問題