3

Ok, this has been covered already, for example here: static array class variable "multiple definition" C++

But I am missing some details here.

I have got the following classes: 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);
}

and 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

The linker complains of multiple definitions. But I am not quite sure, why. Do the #ifndef, #define preprocessor directives not help? I kind of get it that md2Loader.h get included to both Model.cpp and Model.h. When I do the implementation in Model.h and leave Model.cpp away it will compile and link just fine. I thought, that the directives for the preprocessor prevent that from happening, but obviously I am missing something there.

Community
  • 1
  • 1
kimsay
  • 311
  • 3
  • 15

1 Answers1

6

You need to either inline the function defined in header file or move it into a source file. Because that function will be appeared in multiple translation unit.

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

See more on inline specifier

There may be more than one definition of an inline function or variable (since C++17) in the program as long as each definition appears in a different translation unit. For example, an inline function or an inline variable (since C++17) may be defined in a header file that is #include'd in multiple source files.

Graham
  • 7,431
  • 18
  • 59
  • 84
Danh
  • 5,916
  • 7
  • 30
  • 45
  • thanks! Could you provide a link to the theory behind it, please. Coming from Java background this is sometimes a bit confusing to me... – kimsay Oct 27 '16 at 16:36
  • @kimsay added a bit more documentation – Danh Oct 27 '16 at 16:39
  • @kimsay `inline` marks a function as OK to be in different translation units. The ODR allows the compiler to assume if it finds multiple definitions that they are all identical, and it can consolidate them. Java doesn't have `#include` so you never have the problem in the first place. – Mark Ransom Oct 27 '16 at 16:58