2012-11-19 100 views
13

假設我有以下代碼:爲什麼我必須重新聲明C++派生類中的重寫函數?

class Iinterface 
{ 
    virtual void abstractFunction()=0; 
}; 

class Derived : public Iinterface 
{ 
    void abstractFunction(); // Do I need this line? 
}; 

Derived::abstractFunction() 
{ 
    // implementation here 
} 

如果我不加這行,我得到編譯錯誤,說:abstractFunctionDerived聲明。我使用的VS 2008.
我不知道爲什麼我需要這個特定的行(不要混淆這與函數定義,這是提供外類聲明),只要我從Iinterface它應該繼承很明顯我已經申報了abstractFunction。這是視覺工作室的問題,還是由C++標準強制執行?

回答

8

如果純虛基函數聲明中的所有派生類中暗示,那麼你就不可能有一個派生類仍然是抽象相對於純虛擬基函數。相反,所有派生類都會產生鏈接器錯誤。這會非常直觀和令人困惑,並且會使語言表達不夠。

此外,它甚至沒有意義:派生類是否抽象的問題在編譯時必須知道無處不在。覆蓋的實現通常只在一個單獨的翻譯單元中提供,所以不可能將您實際上意味着功能被覆蓋的事實傳達給程序的其餘部分。

+0

你總結得更好:) –

+0

我同意,這可能是比我散漫的回答,+1更容易理解。 – OmnipotentEntity

+0

派生類是否抽象可以用C++缺乏的明確的「抽象」關鍵字來知道。 –

0

是的,純虛擬函數的全部重點是強制您在派生類中重寫它;這一聲明是在C++

+0

我所知道的是,我和** **時許覆蓋它,我只是不明白,爲什麼我需要重寫類聲明中函數的原型。爲什麼VS不會推斷它本身? – atoMerz

+0

VS認爲ü忘了這一點梅託德:) – whd

+0

因爲類定義驅動對象層次的設計,如果你願意,正如immillind上面解釋的那樣,您選擇是否包含重寫聲明或不會告訴編譯器相應的方法代碼是否存在。 –

2
  1. 明確的:如果你想創建的class Derived
  2. 沒有對象:如果你想保持class Derived抽象
  3. :如果有一箇中間等級已經超過了功能
    eg在IinterfaceDerived之間有class Intermediate,它已被重寫abstractFunction();所以現在是可選的class Derived覆蓋相同

編輯:隨着改變問題的標題,

我爲什麼要在 C++在派生類中重新聲明重載函數?

這是因爲C++編譯器的語法要求的class(或namespace或文件)的每個成員函數必須在class(或namespace或文件)體內聲明。是它virtual或正常功能。
沒有破壞一致性只是爲virtual職能的好理由。

+1

我認爲OP意識到覆蓋純虛函數的機制。她想知道爲什麼*聲明*在派生類中是必需的。 –

+0

@KerrekSB謝謝,這正是我的意思。 – atoMerz

+0

@KerrekSB,似乎這個問題的標題已經被編輯了。我會修改答案。 – iammilind

1

=0結尾的函數稱爲deleted function,當您不希望使用某些構造函數的對象(例如unique_ptr具有已刪除的副本)時,此函數很有用。

如果virtual函數被刪除,那麼通過標準該類變爲抽象類型。因爲在大多數情況下,類的原型和類的函數體都在單獨的文件中,這意味着除非您在原型中明確指出您重寫了已刪除的虛函數,否則不會覆蓋已刪除的虛函數。編譯器不應該只是簡單地推斷出你想在一個完全不同的文件中看到實現的時候把它放在那裏。

請記住,原型/實現的想法並不是編寫代碼的唯一方法,您也可以將實現正確地放在類中(如果代碼足夠小並且想要內聯函數,則可以實現該實現。 )要做到這一點,你需要再次明確地覆蓋已刪除的虛擬功能。所以,因爲無論如何你需要重寫它,所以你需要在原型中明確地覆蓋它是非常有意義的。該功能仍然被刪除,否則。

對於一個具體的例子:假設你有一個List.hpp,List.cpp和main.cpp中

在List.hpp你有一個抽象類,從抽象類繼承的普通班。主要你#include "List.hpp"而不是List.cpp,對不對?因此,編譯器不知道什麼是在該文件中(直到它試圖對其進行編譯。)如果你沒有覆蓋已刪除的虛擬函數,則編譯器認爲你只是試圖實例化一個抽象類,並拋出一個錯誤。

在另一方面,如果你正在編譯List.cpp,那麼編譯器也會拋出一個錯誤,這個時候抱怨說,你要寫函數實際上並沒有被定義。因爲Base::deletedFunction()不同於Derived::deletedFunction()

+0

謝謝。這是編譯器限制還是C++限制? – atoMerz

+1

C++限制。儘管我會毫不猶豫地將其稱爲限制。只是簡單地說,你必須明確它。從長遠來看,這可以幫助你,imo。 – OmnipotentEntity

相關問題