2013-05-28 16 views
0

一類與此代碼:適當延長在C++

class Plant 
{ 
public: 
    virtual std::string getPlantName(); 
    virtual void setPlantName(std::string s); 

    virtual std::string getPlantType(); 
    virtual void setPlantType(std::string s); 


}; 

class Carrot : public Plant 
{ 
public: 
    Carrot(); 
    ~Carrot(); 

private: 
    std::string _plantName; 

}; 

然後:

#include "Carrot.hpp" 

Carrot::Carrot() 
{ 


} 

Carrot::~Carrot() { } 

std::string Carrot::getPlantName() { return _plantName; } 

我得到一個鏈接錯誤:

Carrot.cpp:16:21: Out-of-line definition of 'getPlantName' does not match any declaration in 'Carrot' 

所以這裏的目標是創建一個Plant類,其他類擴展如class Carrot : public Plant

但是,我不確定的是我可以inline功能Plant,以便我不必在每個類中創建這些getset函數,如胡蘿蔔或豌豆等?

如果我這樣做:

inline virtual std::string getPlantName(return _plantName;); 

將這項工作?然後我會添加std::string _PlantName;class Plant然後當我創建CarrotPlant我得到所有相同的功能和Carrot將有像_plantName等變量,是否正確?

因此,這將是:

class Carrot : public Plant 
{ 
public: 
    Carrot(); 
    ~Carrot(); 

    virtual std::string getPlantName(); 

private: 
    std::string _plantName; 

}; 

或者,如果所有植物都有名字,你可以定義方法:

class Plant 
{ 
public: 
    inline virtual std::string getPlantName(return _plantName;); 
    virtual void setPlantName(std::string s); 

    virtual std::string getPlantType(); 
    virtual void setPlantType(std::string s); 

private: 
    std::string _plantName; 
}; 

class Carrot : public Plant 
{ 
public: 
    Carrot(); 
    ~Carrot(); 
}; 

#include "Carrot.hpp" 

Carrot::Carrot() 
{ 
    setPlantName(CARROT::plantName); 

} 

Carrot::~Carrot() { } 

回答

0

如果Plant類的所有對象都應該有一個類型和名稱,既std::string S,你可能想在基類中那些普通成員:

// Plant.hpp 
class Plant 
{ 
public: 
    Plant(); 
    virtual ~Plant(); // virtual destructor! 
    virtual std::string getPlantName(); 
    virtual void setPlantName(std::string s); 
    virtual std::string getPlantType(); 
    virtual void setPlantType(std::string s); 
protected: 
    std::string _plantName; 
    std::string _plantType; 
}; 

// Plant.cpp 
#include <Plant.hpp> 

std::string Plant::getPlantName() { return _plantName; } 
void Plant::setPlantName(std::string s) { _plantName = s; } 
... same for type 

當創建使用class Carrot : public Plant派生類,即類將具有相同的數據成員和相同的功能。如果需要,您也可以覆蓋它們(感謝virtual關鍵字,使用Plant指針指向Carrot對象時將調用派生類的實現)。

請注意,如果你想確保永不instansiate一個Plant對象,你應該讓任何非通用功能(如DoSomethingTypeSpecific()一個胡蘿蔔或花會做出不同的)純虛,並通過創建一個抽象基類。所有的基類然後來實現這些功能。

這裏的內聯並沒有真正的區別,只是在頭文件或單獨的.cpp文件中定義函數。通常,將實現保存在單獨的文件中是一個好主意,但是如果你願意,這些小的setter和getter可以很容易地被內聯。

+0

這正是我想要做的。所有的「植物」都有這些相同的項目(和其他我沒有包括在內),當擴展時,我想要所有這些相同的東西,並在需要的地方覆蓋。 – Jason

+0

等等,以便在標題中內聯它將是'內聯虛擬std ....'。或者「虛擬內聯......」這個順序並沒有什麼區別(我相信),但是開發人員是否可以通過預期的方式閱讀它? – Jason

+0

你能詳細說一下'純虛擬'嗎?你可以'純粹的虛擬內聯'那些吸氣劑和吸附劑? – Jason

0

您可以通過添加方法的類聲明糾正錯誤在Plant類中(可能在plant.cpp中)。事實上,除非你聲明它是純虛擬的,否則你必須定義它。

0

您需要聲明該函數。

class Carrot : public Plant 
{ 
public: 
    Carrot(); 
    ~Carrot(); 

    std::string getPlantName(); //Add this 

private: 
    std::string _plantName; 

}; 

有兩點要注意:

  • 這不是絕對必要的Carrot::getPlantName是虛擬的,雖然很多C++開發人員認爲這是很好的形式。我個人更喜歡在抽象基類中使用虛擬,並且在具體類中不使用虛擬
  • 您可能需要將virtual ~Plant() {}添加到Plant類。你幾乎總是希望具有虛擬方法的類也具有虛擬析構函數。