遵循单定义规则,但c++抛出重定义错误



c++中非常奇怪的重定义错误,特别是在包括main在内的所有其他文件都没有错误的情况下。

我有我的头(各种动物)和一个实现文件"animals.cpp"

我的标题遵循以下格式:

class Mammal : public Animal{
public:
Mammal(){} //empty constructor
virtual ~Mammal(){} // destructor
void createNewMammalObject(std::string name, std::string trackingNum, std::string nurse, std::string subType, std::string type){}
std::string getSubtype() {}
void setSubtype(std::string subType){}
int getNursing(){}
void setNursing(int nursing){}
void setType(std::string type){}
int getNumEggs(){}
protected:
int nursing;
};

和实现文件中的实现看起来像:

Mammal::Mammal() {} //empty constructor
virtual Mammal::~Mammal(){} // destructor
void Mammal::createNewMammalObject(std::string name, std::string code,std::string nurse,std::string subType, std::string type){
this->setNursing(nursing);
this->setSubType(subType);
this->createNewAnimalObject(name, trackingNum,subType,type);
}
std::string Mammal::getSubtype() {
return subType;
}
void Mammal::setSubtype(std::string subType) {
this->subType = subType;
}
int Mammal::getNursing() {
return this->nursing;
}
void Mammal::setNursing(int nursing) {
this->nursing = nursing;
}
void Mammal::setType(std::string type){
this->type = type;
}
int Mammal::getNumEggs() {
return 0;
}

实现文件的#include是:

#include "animal.h"
#include "oviparous.h"
#include "mammal.h"
#include "crocodile.h"
#include "goose.h"
#include "pelican.h"
#include "bat.h"
#include "seaLion.h"
#include "whale.h"

所有的头和实现都遵循这种格式来遵循One-Definition,除了animal.h,它是一个抽象类,并且包含函数定义。所有其他函数肯定只定义一次。然而,在构建项目之后,实现文件中的每个函数都说它是一个重新定义,并指向头作为原始定义。我非常困惑。这是Eclipse的问题吗?我的抽象类应该像其他头文件一样在我的实现文件中定义吗?

关于你的头文件(集中在一个行,但他们几乎所有有同样的问题):

std::string getSubtype() {}
//                       ^^
//                    see here

这是空函数体的定义,非定义声明将是:

std::string getSubtype();

您在头文件实现文件中都定义函数的事实几乎肯定是您违反ODR的原因。

还有两点,都不是致命的:


首先,通常首先设置基类的东西,以便派生类可以覆盖特定的属性。这将导致重新排序(在还修复了护士/护理差异之后):

#include <string>
void Mammal::createNewMammalObject(
std::string name,
std::string code,
std::string subType,
std::string type,
std::string nursing  // moved to end, just a foible of mine.
) {
this->createNewAnimalObject(name, trackingNum, subType, type);
// Could now modify below any of those items in previous line.
this->setNursing(nursing);
this->setSubType(subType);
}

第二,通常让构造函数做尽可能多的工作,而不是让一些函数来设置。后者会导致如果忘记调用该函数,则构造的对象可能处于某种奇怪的不可用状态。

我会看一些更像这样的东西:

#include <string>
class Animal {
public:
Animal(
std::string name,
std::string trackingNum,
std::string subType,
std::string type
)
:   m_name(name)
,   m_trackingNum(trackingNum)
,   m_subType(subType)
,   m_type(type)
{
// Other less important initialisation and possibly also
// throwing exception if any of those four above are invalid.
}
private:
std::string m_name;
std::string m_trackingNum;
std::string m_subType;
std::string m_type;
};
class Mammal :Animal {
public:
Mammal(
std::string name,
std::string trackingNum,
std::string subType,
std::string type,
std::string nursing
)
:   Animal(name, trackingNum, subType, type)
,   m_nursing(nursing)
{
// Ditto on more initialisation and throwing
// for bad nursing value.
}
private:
unsigned int m_nursing;
};
int main() {}

最新更新