正确扩展C ++中的类

时间:2013-05-28 22:46:31

标签: c++ macos class object composition

使用此代码:

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,然后当我从Carrot创建Plant时,我会获得所有相同的函数,而Carrot会有_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() { }

3 个答案:

答案 0 :(得分:0)

您可以通过将方法添加到类声明中来纠正错误:

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

  virtual std::string getPlantName();

private:
  std::string _plantName;

}; 

或者,如果所有植物都有名称,您可以在Plant类中定义方法(可能在plant.cpp中)。实际上,除非将其声明为纯虚拟,否则必须对其进行定义。

答案 1 :(得分:0)

如果Plant类的所有对象都应该有std::string个类型和名称,那么您可能需要基类中的那些公共成员:

// 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指针时,将调用派生类的实现。

请注意,如果你想确保永远不会实现Plant对象,你应该制作任何非常见的函数(比如Carrot或Flower会做的不同的DoSomethingTypeSpecific()纯虚拟,并通过创建抽象基类。然后,所有基类都将具有来实现这些功能。

这里的内联并没有真正的区别,只需要在头文件或单独的.cpp文件中定义函数。通常,将实现保存在单独的文件中是个好主意,但如果您愿意,可以很容易地将这些小的setter和getter内联。

答案 2 :(得分:0)

您需要声明该功能。

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

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

private:
    std::string _plantName;

};

几点说明:

  • Carrot::getPlantName并非绝对必须是虚拟的,尽管许多C ++开发人员认为它是好的形式。我个人更喜欢只在抽象基类中使用虚拟,而在具体类中使用none
  • 您可能需要将virtual ~Plant() {}添加到Plant课程。您几乎总是希望使用虚方法的类也具有虚拟析构函数。