简体   繁体   English

遵循单一定义规则,但 C++ 引发重定义错误

[英]One-Definition Rule Followed, but C++ throws Redefinition Error

Very strange redefinition error in C++, especially as every other file including main is error-free. C++ 中非常奇怪的重新定义错误,尤其是包括 main 在内的所有其他文件都没有错误。

I have my headers (various animals) and an implementation file "animals.cpp".我有我的标题(各种动物)和一个实现文件“animals.cpp”。

My headers follow the format:我的标题遵循以下格式:

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;
};

And implementation in the implementation file looks like:实现文件中的实现如下所示:

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;
}

My #includes for the implementation file are:我的实现文件的#includes 是:

#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"

All headers and implementation follow this format to follow the One-Definition, except for animal.h which is an abstract class and does contain function definitions.所有头文件和实现都遵循此格式以遵循单一定义,除了作为抽象 class 并且确实包含 function 定义的animal.h。 All other functions are definitely only defined once.所有其他函数肯定只定义一次。 However, after building the project, EVERY function in the implementation file is saying it's a redefinition and pointing back to the headers as the original definition.但是,在构建项目之后,实现文件中的每个 function 都说它是重新定义并指向头文件作为原始定义。 I'm incredibly confused.我非常困惑。 Is this an Eclipse problem?这是 Eclipse 问题吗? Should my abstract class be defined in my implementation file like the other headers?我的抽象 class 是否应该像其他头文件一样在我的实现文件中定义?

Regarding your header file (focussing on one line but they pretty much all have the same problem):关于您的 header 文件(集中在一行,但它们几乎都有相同的问题):

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

This is a definition of a function with an empty body, a non-definition declaration would be:这是具有空主体的 function 的定义,非定义声明将是:

std::string getSubtype();

The fact that you're defining functions in both the header and implementation file is almost certainly the cause of your ODR violations.您在 header实现文件中定义函数的事实几乎肯定是您违反 ODR 的原因。

And just two other points, neither necessarily fatal:还有另外两点,不一定是致命的:


First, it's normal to set up the base class stuff first so that derived classes can override specific properties.首先,首先设置基本的 class 东西是正常的,这样派生类就可以覆盖特定的属性。 That would result in a reordered (after also fixing the nurse/nursing discrepancy):这将导致重新排序(在修复护士/护理差异之后):

#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);
}

Second, it's usual for the constructor to do as much work as possible, rather than having some function set things up.其次,构造函数通常会做尽可能多的工作,而不是让一些 function 进行设置。 The latter leads to the possibility that a constructed object may be in some weird unusable state if you forget to call that function.后者导致如果您忘记调用 function,则构造的 object 可能处于一些奇怪的无法使用的 state 中。

I would be looking at something more along the lines of:我会看更多的东西:

#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() {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM