2013-09-11 142 views
1

我想創建一個具有純虛函數的抽象類,該純虛函數由非純虛擬的構造函數調用。下面是我的文件class.hpp在非純虛函數中使用純虛函數的C++抽象類

#ifndef __CLASS_HPP__ 
#define __CLASS_HPP__ 

#include <iostream> 

class Parent { 
public: 
    Parent(){ 
    helloWorld(); // forced to say hello when constructor called      
    }; 
    virtual void helloWorld() = 0; // no standard hello...        
}; 

class Child : public Parent { 
public: 
    void helloWorld(){ // childs implementation of helloWorld       
    std::cout << "Hello, World!\n"; 
    }; 
}; 

#endif 

在這個例子中,我有了一個純虛函數helloWorld()一個父類。我希望每個派生類在構造函數被調用時都會說「hello」;因此helloWorld()爲什麼在父類構造函數中。但是,我希望每個派生類都是FORCED,以選擇它如何去說「你好」,而不是使用默認方法。這可能嗎?如果我嘗試用g ++編譯這個,我得到了構造函數正在調用純虛函數的錯誤。我main.cpp是:

#include "class.hpp" 

int main(){ 
    Child c; 
    return 0; 
} 

我使用g++ main.cpp -o main.out編譯和所產生的誤差是:

In file included from main.cpp:1:0: 
class.hpp: In constructor ‘Parent::Parent()’: 
class.hpp:9:16: warning: pure virtual ‘virtual void Parent::helloWorld()’ called from constructor [enabled by default] 

對於如何在合法的方式獲得了類似的設置有什麼建議?

新問題

DYP帶來了我的注意,一個構造函數不使用任何重寫功能,所以我希望能夠做的是不可能在我把它設置的方式。但是,我仍然想強制任何派生的構造函數調用函數helloWorld(),有沒有辦法做到這一點?

+0

呼叫從一個構造函數虛函數(同一個對象的)的構造函數是危險的,因爲它不」 t調用派生類的重寫。在這種情況下,它嘗試調用純粹的「Parent :: helloWorld」,因此*警告*(純虛函數仍然可以實現)。您可以通過參數將派生類中的字符串傳遞給基類ctor,然後在基類中執行輸出。也有可能:2階段初始化。 – dyp

+0

基類依賴於這樣的派生類似乎很奇怪。你能詳細說明你想解決的問題嗎?根據具體情況,可能有其他選項可用。 –

+0

在我的實際問題中,我有一個保存模擬數據的類。但是,在仿真中有很多功能取決於用戶的偏好。我的基類是一個抽象類,它具有讀入大量數據並存儲它的構造函數,但留下了一些抽象函數(這些函數取決於uesr首選項)。所以我希望任何用戶都被迫以相同的方式讀取數據,但也被迫實現這些抽象函數。 – nick

回答

1

爲什麼不簡單地將它添加到每個子類的構造函數中?

如果你想避免每次寫它在構造函數(或者甚至逃課或繼承它),那麼你可以使用CRTP:

class Parent { 
public: 
    Parent(){}; 
    virtual void helloWorld() = 0; // no standard hello...        
}; 

template <typename Par> 
class ParentCRTP: public Parent { 
public: 
    ParentCRTP(){ 
    Par::doHelloWorld(); 
    }; 
    virtual void helloWorld(){ 
    Par::doHelloWorld(); 
    } 
}; 

class Child : public ParentCRTP<Child> { 
public: 
    static void doHelloWorld(){ // childs implementation of helloWorld       
    std::cout << "Hello, World!\n"; 
    }; 
}; 

這種做法不會給你一個指向子類你的孩子的hello方法 - 此時類實例只有Parent實例,沒有有效的Child指針可以獲得。爲了在構造後強制執行Child的方法,您只能使用兩個階段初始化:首先使用構造函數創建類實例,然後使用單獨的方法初始化它。

除此之外,像這樣的問題可能是重新考慮你的設計的暗示。你不應該強迫你的類以特定的方式初始化自己。

2

你在做什麼是非法的。

爲了用C++定義一個抽象類,你的類必須至少有一個純虛函數。在你的情況下

virtual void helloWorld() = 0; 

在這種情況下,你是對的。

但是你的純虛函數沒有任何實現,因爲它是一個純虛函數。因此,它是非法的同一類的constuructor調用純虛函數。(在一流水平的純虛函數沒有任何實現)

所以,

Parent(){ 
helloWorld(); // forced to say hello when constructor called      
}; 

這是非法的。

如果你願意,你可以實現你的純虛函數在派生類中,然後調用helloWorld()從派生類

+0

這不會是我想要的。我希望每個子類都被迫調用'helloWorld()'。我寫的代碼將被其他人使用,我希望他們被迫調用該函數。 – nick

+0

我明白了。這就是爲什麼在父類構造函數中調用'helloWorld()'的原因。但是,情況是,如果你想定義一個抽象類,它必須包含至少一個純虛函數。在你的情況下,它是'helloWorld()',它在父類級別沒有實現。 – ANjaNA

+0

@nick你清楚嗎? – ANjaNA