zoukankan      html  css  js  c++  java
  • C++的multiple definition of *** first defined here错误

    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 _MYCLASS1_H_
    #define _MYCLASS1_H_
     
    #include "myClass.h"
    #include <iostream>
     
    class myClass1
    {
    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
  • 相关阅读:
    javascript 下拉列表 自动取值 无需value
    gopkg:一种方便的go pakcage管理方式
    编译GDAL使用最新的HDF库配置文件
    leetcode:程序员面试技巧
    【Unity Shader实战】卡通风格的Shader(一)
    GDAL1.11版本对SHP文件索引加速测试
    【Unity Shaders】Shader学习资源和Surface Shader概述
    关于rowid的函数
    java基本类型的大小
    【转载】oracle之rowid详解
  • 原文地址:https://www.cnblogs.com/Adrian99/p/3145762.html
Copyright © 2011-2022 走看看