多重定义 C++

3

好的,这个问题已经有人讨论过了,例如在这里:static array class variable "multiple definition" C++

但是我在这里缺少一些细节。

我有以下类: Foo.cpp

#include <iostream>
#include "Model.h"

    int main(int argc, char** argv){
        std::cout << "hello" << std::endl;
        return 0;
    }

Model.h

#ifndef MODEL_H
#define MODEL_H

#include <string>
#include "md2Loader.h"

class Model{
    public:
    Model();
    Model(const std::string& model_file);

    private:
    md2_header_t header;
    modelData_t model;
};

#endif

Model.cpp

#include "Model.h"
#include "md2Loader.h"

Model::Model(){}

Model::Model(const std::string& model_file){
    model = md2Loader::load_model(model_file);
}

以及md2Loader.h

#ifndef MD2LOADER_H
#define MD2LOADER_H

struct modelData_t{
    int numVertices;
    int numTextures;
    // etc
};

struct md2_header_t {
    std::string version;
};

class md2Loader{
public:
    md2Loader(){};
    static modelData_t load_model(const std::string& model_file);
};

modelData_t md2Loader::load_model(const std::string& model_file){
    modelData_t result;
    result.numVertices = 1000;
    result.numTextures = 10;

    return result;
}


#endif

链接器报告了多个定义问题,但我不太确定原因。难道#ifndef,#define预处理器指令没有起作用吗?我有点明白md2Loader.h被包含在Model.cpp和Model.h中的情况。当我在Model.h中实现并且不使用Model.cpp时,它将编译和链接得很好。我认为预处理器的指令可以防止这种情况发生,但显然我在那方面缺少了一些东西。

1
你需要在头文件中定义的函数中使用inline - Danh
“#ifndef和#define预处理指令没有起到帮助作用吗?” - Lightness Races in Orbit
1个回答

6

您需要将头文件中定义的函数进行内联或者将其移动到源文件中。因为该函数将在多个翻译单元中出现。

inline modelData_t md2Loader::load_model(const std::string& model_file){
    modelData_t result;
    result.numVertices = 1000;
    result.numTextures = 10;
    return result;
}

更多内容请参见内联说明符

在程序中,只要每个定义出现在不同的翻译单元中,就可以有一个以上的内联函数或变量(自C++17起)。例如,内联函数或内联变量(自C++17起)可以在一个头文件中定义,在多个源文件中#include。


谢谢!请提供一个链接来解释它的理论基础。作为来自Java背景的人,这有时对我来说有点困惑... - kimsay
@kimsay 添加了更多的文档说明。 - Danh
@kimsay inline 标记函数可以在不同的翻译单元中使用。ODR 允许编译器假设如果它发现多个定义,那么它们都是相同的,并且可以合并它们。Java 没有 #include,所以你从一开始就不会遇到这个问题。 - Mark Ransom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接