http://yumaoshu.com/?p=235
C++的multiple definition of *** first defined here错误
这两天写程序碰到个问题。那么久那么久终于解决了,其实很简单点问题。但既然付出了这么长时间,就让我永远记住它吧。。写篇日志(前面有两篇写了一半的大家说的那种垃圾流水账文,都没发……这里闲置好久好久了)
首先我把出现这个现象的情况简化。我专门写了个测试程序,共有如下几个文件
myClass.h |
myClass1.h |
myClass1.cpp |
main.cpp |
myClass.h |
myClass1.h |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#ifndef _MYCLASS_H_
#define _MYCLASS_H_
#include <iostream>
class myClass
{
public :
int print();
};
int myClass::print()
{
std::cout << "YuMS" << "
" ;
return 0;
}
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#ifndef _MYCLASS1_H_
#define _MYCLASS1_H_
#include "myClass.h"
#include <iostream>
class myClass1
{
public :
myClass myclass;
int print();
};
#endif
|
|
myClass1.cpp |
main.cpp |
1
2
3
4
5
6
7
8
|
#include <iostream>
#include "myClass1.h"
int myClass1::print()
{
myclass.print();
return 0;
}
|
|
1
2
3
4
5
6
7
8
|
#include "myClass1.h"
int main()
{
myClass1 myclass1;
myclass1.print();
return 0;
}
|
|
使用g++进行生成
1
|
g++ -o main.exe main.cpp myClass1.cpp
|
得到的结果是
1
2
3
4
5
6
|
C:UsersYuMSAppDataLocalTempccU3jb7q.o:myClass1.cpp:(.text+0x0): multiple d
efinition of `myClass::print()'
C:UsersYuMSAppDataLocalTempccldoy68.o:main.cpp:(.text+0x0): first defined
here
collect2: ld returned 1 exit status
shell returned 1
|
大约分析一下,原因从我这种弱爆了的人嘴里说出来大约应该是
main.cpp和myClass1.cpp都include了myClass1.h
虽然myClass1.h有include保护,但也招架不了分别编译
所以链接的时候导致无辜的myClass.h挂掉了
注意到了么?!
是myClass.h挂掉了,不是myClass1.h。
myClass.h其实是不无辜的,它的写法太2了。把该写在本应有的myClass.cpp中的print函数的实现写在了自己的外面。
为什么我会写出这么2的程序呢?那是因为在用到template的类中只能这样写。我就认为在一般的程序里显然也能这样,就那么一个函数,写个cpp不爽。
于是触发了大boss,费了我这么长时间。
事实上
“模板定义很特殊。由template <…> 处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知。在编译器和连接器的某一处,有一机制能去掉指定模板 的多重定义。所以为了容易使用,几乎总是在头文件中放置全部的模板声明和定义。”《C++编程思想》
template的只能这样(或用export,本文不作讨论),而这个不能……
解决方法是:分开写,如下
myClass.h |
myClass.cpp |
myClass1.h |
myClass1.cpp |
main.cpp |
myClass.h |
myClass1.h |
1
2
3
4
5
6
7
8
9
10
11
12
|
#ifndef _MYCLASS_H_
#define _MYCLASS_H_
#include <iostream>
class myClass
{
public :
int print();
};
#endif
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#ifndef _MYCLASS1_H_
#define _MYCLASS1_H_
#include "myClass.h"
#include <iostream>
class myClass1
{
public :
myClass myclass;
int print();
};
#endif
|
|
myClass1.cpp |
main.cpp |
1
2
3
4
5
6
7
8
|
#include <iostream>
#include "myClass1.h"
int myClass1::print()
{
myclass.print();
return 0;
}
|
|
1
2
3
4
5
6
7
|
#include "myClass1.h"
int main()
{
myClass1 myclass1;
myclass1.print();
return 0;
}
|
|
myClass.cpp |
|
1
2
3
4
5
6
7
8
|
#include <iostream>
#include "myClass.h"
int myClass::print()
{
std::cout << "YuMS" << "
" ;
return 0;
}
|
|
|
使用g++进行生成
1
|
g++ -o main.exe main.cpp myClass.h myClass1.cpp
|
另附程序(若将myClass.h故意写成模版就没事了……好玩)
myClass.h |
myClass1.h |
myClass1.cpp |
main.cpp |
myClass.h |
myClass1.h |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#ifndef _MYCLASS_H_
#define _MYCLASS_H_
#include <iostream>
template < class T>
class myClass
{
public :
int print();
};
template < class T>
int myClass<T>::print()
{
std::cout << "YuMS" << "
" ;
return 0;
}
#endif
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#ifndef _MYCLASS 1 _H_
#def ine _MYCLASS 1 _H_
#include "myClass.h"
#include <iostream>
class myClass 1
{
public:
myClass<int> myclass;
int print ();
};
#endif
|
|
myClass1.cpp |
main.cpp |
1
2
3
4
5
6
7
8
|
#include <iostream>
#include "myClass1.h"
int myClass1::print()
{
myclass.print();
return 0;
}
|
|
1
2
3
4
5
6
7
8
|
#include "myClass1.h"
int main()
{
myClass1 myclass1;
myclass1.print();
return 0;
}
|
|
使用g++进行生成
1
|
g++ -o main.exe main.cpp myClass1.cpp
|