dude
dude

Reputation: 31

linker error when function definition is outside class

I have files::

//ClassA.h
#ifndef ClassA_H
#define ClassA_H

#pragma once
class ClassA
{
public:
void func1(){


}
ClassA(void) {

}
~ClassA (void) {


}

};

#endif

//ClassA1.h
#include "ClassA.h"

class ClassA1 {
    ClassA<2> b;
};


//ClassA1.cpp

#include "ClassA1.h"

//main_file.cpp
#include "ClassA1.h"
#include "iostream"
int main (int argc , char** argv) {

    std::cout<<"in main"<<std::endl;
}

So this compiles fine...As soon as i define function of class ClassA outside the class in Class.h i get following error during build

1>  LINK : c:\users\adudeja\documents\visual studio 2010\Projects\Test\Debug\Test.exe not found or not built by the last incremental link; performing full link
1>ClassA1.obj : error LNK2005: "public: void __thiscall ClassA::func1(void)" (?func1@ClassA@@QAEXXZ) already defined in main_file.obj
1>ClassA1.obj : error LNK2005: "public: __thiscall ClassA::ClassA(void)" (??0ClassA@@QAE@XZ) already defined in main_file.obj
1>ClassA1.obj : error LNK2005: "public: __thiscall ClassA::~ClassA(void)" (??1ClassA@@QAE@XZ) already defined in main_file.obj
1>c:\users\adudeja\documents\visual studio 2010\Projects\Test\Debug\Test.exe : fatal error LNK1169: one or more multiply defined symbols found

So what is the difference between defining function outside class and inside class.

Below is the non working code...

#ifndef ClassA_H
#define ClassA_H

#pragma once
class ClassA
{
public:
void func1();
ClassA(void);
~ClassA(void);

};
void ClassA::func1(){


}
ClassA::ClassA(void) {

}
ClassA::~ClassA (void) {


}

#endif

Upvotes: 0

Views: 1104

Answers (2)

Jonathan Wakely
Jonathan Wakely

Reputation: 171393

So what is the difference between defining function outside class and inside class.

When you define it in the class body it is implicitly inline, and an inline function can be defined in multiple files.

A non-inline function must be defined exactly once only.

So either put the non-inline definition into a single .cpp file, not in a header included by multiple files, or define it with the inline keyword.

Upvotes: 3

DevSolar
DevSolar

Reputation: 70353

OK, let's see...

In your example, no function is defined outside the class declaration.

Both ClassA1.cpp and main_file.cpp "see" the definition of ClassA. Since all functions defined inside a class declaration are considered inline, i.e. the linker does not see it as a seperate function at all, and has nothing to complain about.

But if you put the definition of e.g. func1() outside the class declaration (but still in ClassA), it's no longer considered inline, it's a seperate function. But as it is still visible to two compilation units, it gets compiled in both translation units.

So when you attempt to link the two object files together, you got two instances of func1(), and the linker complains.

The solution is to either:

  1. define a function inside the class declaration, or
  2. define the function in one seperate translation unit (ClassA.cpp), and link with that.

Using templates limits your options somewhat, as template code must be visible to each translation unit it is used in, i.e. you cannot just declare it in a header and implement it elsewhere, leaving you with only option 1. above.


Post-code-review:

ClassA.hpp:

#ifndef ClassA_HPP
#define ClassA_HPP

class ClassA
{
    public:
        ClassA();
        ~ClassA();
        void func1();
};

#endif

ClassA.cpp:

#include "ClassA.hpp"

void ClassA::func1()
{
    // ...
}

ClassA::ClassA()
{
    // ...
}

ClassA::~ClassA()
{
    // ...
}

ClassA1.hpp:

#ifndef ClassA1_HPP
#define ClassA1_HPP

#include "ClassA.hpp"

// Your example still assumed that ClassA is a template,
// so I twisted that into an inheritance instead since
// ClassA isn't a template anymore, and if it *were* a
// template, it would change things significantly.

// Perhaps trying too much at once?

class ClassA1 : public ClassA
{
    // ...
};

#endif

ClassA1.cpp:

#include "ClassA1.hpp"

// ...

main_file.cpp:

#include "ClassA1.hpp"

#include <iostream>

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

Upvotes: 0

Related Questions