2013-11-22 125 views
3

避免「純虛函數調用」我有理由新的C++,所以我想道歉,如果這個問題的水平低於這裏通常的標準一點點 -在派生類C++

我試圖讓幾個類從具有虛函數定義的基類繼承,然後我想創建一個MainClass *數組,它可以包含所有的派生類,以便輸出派生的+定義的虛函數。

我收到錯誤「R6025:純虛函數調用」 - 我不知道爲什麼,我假設 - 當被調用時 - 使用子類中該函數的更新定義。

這裏是我的代碼:

基地:

class mitarbeiter 
{ 
public: 
    mitarbeiter(string name, int nummer); 
    ~mitarbeiter(void); 
    virtual void einkommen() = 0; 
protected: 
    string name; 
    int nummer; 

}; 

Derived1:

#include "mitarbeiter.h" 
class lohnempfaenger : public mitarbeiter 
{ 
public: 
    lohnempfaenger(int stundenlohn, int anzahlStunden, string name, int nummer); 
    ~lohnempfaenger(void); 
    void einkommen(); 
private: 
    int stundenlohn; 
    int anzahlStunden; 
}; 

衍生2:

#include "mitarbeiter.h" 
#include <string> 
class angestellter : public mitarbeiter 
{ 
public: 
    angestellter(int gehalt, string name, int nummer); 
    ~angestellter(void); 
    void einkommen(); 
private: 
    int gehalt; 
}; 

實施 「einkommen()」 中衍生1 :

void lohnempfaenger::einkommen() 
{ 
    cout << "Lohnempfaenger, Name: " << this->name << ", Gesamtlohn: " << this->stundenlohn*this->anzahlStunden << "\n"; 
} 

在派生2執行 「einkommen()」:

void angestellter::einkommen() 
{ 
    cout << "Angestellter, Name: " << this->name << ", Einkommen: " << this->gehalt << "\n"; 
} 

陣列的宣言主要方法:

mitarbeiter* mitPtr[5]; 
mitPtr[0] = &angestellter(/*values...*/); 
//error 
mitPtr[0]->einkommen(); 

構造:

mitarbeiter::mitarbeiter(string name, int nummer) 
{ 
    this->name = name; 
    this->nummer = nummer; 
} 

angestellter::angestellter(int gehalt, string name, int nummer):mitarbeiter(name, nummer) 
{ 
    this->gehalt = gehalt; 
} 

lohnempfaenger::lohnempfaenger(int stundenlohn, int anzahlStunden, string name, int nummer):mitarbeiter(name, nummer) 
{ 
    this->stundenlohn = stundenlohn; 
    this->anzahlStunden = anzahlStunden; 
} 

由於一個很多!

+3

你可以嘗試整理一個我們可以在單個步驟中編譯的獨立示例文件嗎? –

+1

void angestellter :: einkommen();應該聲明爲虛擬 – jbh

+3

與你的問題無關,但'mitarbeiter'的析構函數應該是'virtual',否則如果你通過指向'mitarbeiter'的'instance'刪除派生實例,你將會得到Udefined Behavior。 – Angew

回答

7

現在你告訴我們,你實際上是如何初始化的指針,現在的問題是:

mitPtr[0] = &angestellter(/*values...*/); 

指向一個臨時對象,它在聲明的最後銷燬。之後使用指針會導致未定義的行爲。

你需要一個非臨時變量指向:

angestellter a(/*values...*/); 
mitPtr[0] = &a; 

或者是一個動態分配的對象:

mitPtr[0] = new angestellter(...); 

在這種情況下,不要忘記將其刪除;並且不要忘記給基類一個虛擬析構函數,以便它可以被刪除。您可能會考慮使用智能指針爲您刪除它; std::unique_ptr將是理想的。

+0

啊,我明白 - 我從來沒有想過會對它產生影響 - 謝謝! –

+3

@Dennis爲了記錄,你得到「純虛擬調用」的原因是因爲調用析構函數時,它會將類的vtable重置爲下一個。因此,當調用'〜angestellter'時,它會將類的函數重置爲'mitarbeiter'的函數 - 這就是爲什麼如果您嘗試在'〜angestellter'中調用'einkommen()'時會遇到同樣的問題。所以當你調用'einkommen()'時你訪問的是無效內存,但是內存可能仍然包含它的最後一個有效內容,這是指向基類中純標記的指針。 –

0

我猜你在運行時看到的錯誤消息是說mitarbeiter :: einkommen()被調用。

你的主代碼聲稱是分配一個新的天使,其代碼你沒有提供,但有幾個可能的地方,這個電話可以隱藏。

如果mitarbeiter :: mitarbeiter調用einkommen(),無論您指定給新的類型是什麼類型,都會得到mitarbeiter :: einkommen()。這似乎是最有可能的地方。

其他可能性是明確調用angestellter :: angestellter()或angestellter :: einkommen()中完全合格的mitarbeiter :: einkommen()。