2012-06-27 65 views
5

我有一個抽象基類,並希望在派生類中實現一個函數。爲什麼我必須再次在派生類中聲明函數?爲什麼界面需要重新聲明?

class base { 
public: 
    virtual int foo(int) const = 0; 
}; 

class derived : public base { 
public: 
    int foo(int) const; // Why is this required? 
}; 

int derived::foo(int val) const { return 2*val; } 

回答

7

請考慮派生類定義可能位於標題中,而其實現可能位於源文件中。標題通常包含在多個位置(「翻譯單元」)中,每個位置都將獨立編譯。如果你沒有聲明覆蓋,那麼編譯器就不會在任何其他翻譯單元中知道它。

+0

這是否意味着,如果我不重新聲明派生類中的函數,編譯器將不會查找派生類的重載實現? – Michael

+0

@邁克爾:是的,我認爲這是正確的。 –

4

使得純virtual在基類中的函數的意圖是,派生類必須覆蓋它並提供其自己的實現。
請注意,該類中存在純虛函數會使該類爲Abstract class。簡而言之,該類充當創建更多具體類的接口。一個不能創建Abstract類的對象。

如果您不覆蓋派生類中的純虛函數,那麼派生類僅包含繼承的Base類純虛函數,它本身也充當Abstract類。一旦您的派生類是抽象的,它就不能實例化。
所以爲了讓你的派生類被實例化,它需要重載並因此聲明純虛函數。

+0

你說得對。但是,即使基類不是抽象的,如果我想覆蓋實現,我確實需要重新聲明該函數。 – Michael

1

It is to override the abstraction of the base class

如果你不重新聲明它,那麼你的派生類也是一個抽象類。如果你這樣做,你現在有一個非抽象類型的基地。

2

你可能會認爲,編譯器可以推斷,你將不得不提供derived::foo()實現,但derived也可能是一個抽象類(事實上這就是如果你沒有在derived聲明foo()你會得到什麼)

1

因爲層次結構可能有更多圖層。

struct Base { 
    virtual void foo() const = 0; 
    virtual void bar() const = 0; 
}; 

struct SuperBase: Base { 
    virtual void bar() const override; 
}; 

struct Concrete: SuperBase { 
    virtual void foo() const override; 
}; 

這裏,SuperBase沒有爲foo提供一個實現,這需要以某種方式表示。

1

雖然你不能實例化純虛函數的類,你仍然可以創建這樣一個類:

class base { 
public: 
    virtual int foo(int) const = 0; 
}; 

class derived : public base { 
public: 
}; 

class very_derived : public derived { 
public: 
    virtual int foo(int) const { return 2; } 
}; 

派生類仍然是一個抽象類,不能因爲它實例化不會覆蓋foo。在實例化類之前,您需要聲明foo的非純虛擬版本,即使您沒有立即定義foo。

相關問題