【问题标题】:One-Definition Rule Followed, but C++ throws Redefinition Error遵循单一定义规则,但 C++ 抛出重定义错误
【发布时间】:2021-03-01 00:21:29
【问题描述】:

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

我的实现文件的#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"

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

【问题讨论】:

    标签: c++ c++11 redefinition


    【解决方案1】:

    关于你的头文件(专注于 one 行,但他们几乎 all 有同样的问题):

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

    这是一个函数体的定义,一个非定义的声明应该是:

    std::string getSubtype();
    

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

    还有另外两点,不一定是致命的:


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

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

    【讨论】:

    • 谢谢!我不知道有什么区别。编辑后,没有错误!
    猜你喜欢
    • 2016-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 2021-02-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多