关于c++:模板的分离编译问题

7次阅读

共计 3194 个字符,预计需要花费 8 分钟才能阅读完成。

存在问题的代码:

test.h:

#include <iostream>
using namespace std;
template<class T1,class T2>
void func(T1 t1,T2 t2);

test.cpp:

#include "test.h"
using namespace std;
template<class T1,class T2>
void func(T1 t1,T2 t2)
{cout<<t1<<t2<<endl;}

main.cpp:

#include "test.h"

int main()
{string str("ljt");
    int i=5;
    func(str,5);
}

编译后果:

[root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test
/tmp/ccp1HXnh.o:在函数‘main’中:main.cpp:(.text+0x5d):对‘void func<std::string, int>(std::string, int)’未定义的援用
collect2: 谬误:ld 返回 1

阐明了在 main.cpp 中没有找到函数 func 的定义。

查看起因:
对 test.cpp 只进行编译不进行链接:

[root@localhost cpptest]# g++ -c test.cpp 
[root@localhost cpptest]# nm -C -n test.o 
                 U __cxa_atexit
                 U __dso_handle
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
0000000000000000 t __static_initialization_and_destruction_0(int, int)
0000000000000000 b std::__ioinit
000000000000003d t _GLOBAL__sub_I_test.cpp

会发现符号表中不存在 func 函数,也就是编译出的二进制文件没有为 func 分配内存空间。
起因是:模板只有在应用的时候才进行实例化。

改过后代码:

test.cpp:

#include "test.h"
using namespace std;
template<class T1,class T2>
void func(T1 t1,T2 t2)
{cout<<t1<<t2<<endl;}

void func1(string str,int num){func(str,num);    // 实例化,调配空间
}

编译后:

[root@localhost cpptest]# g++ -c test.cpp    //-c:只编译不链接
[root@localhost cpptest]# nm -C -n test.o
                 U __cxa_atexit
                 U __dso_handle
                 U __gxx_personality_v0
                 w __pthread_key_create
                 U _Unwind_Resume
                 U std::ostream::operator<<(int)
                 U std::ostream::operator<<(std::ostream& (*)(std::ostream&))
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&)
                 U std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()
                 U std::ios_base::Init::Init()
                 U std::ios_base::Init::~Init()
                 U std::cout
                 U std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
                 U std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
0000000000000000 W void func<std::string, int>(std::string, int)
0000000000000000 T func1(std::string, int)
0000000000000000 b std::__ioinit
0000000000000000 r __gthread_active_p()::__gthread_active_ptr
0000000000000063 t __static_initialization_and_destruction_0(int, int)
00000000000000a0 t _GLOBAL__sub_I__Z5func1Ssi

能够看到函数符号 func1(std::string, int)、void func<std::string, int>(std::string, int)。

[root@localhost cpptest]# g++ test.cpp test.h main.cpp -o test
[root@localhost cpptest]# ls -rtl
总用量 32
-rw-r--r-- 1 root root    92 12 月 21 10:41 test.h
-rw-r--r-- 1 root root   172 12 月 21 13:00 test.cpp
-rw-r--r-- 1 root root    86 12 月 21 13:00 main.cpp
-rw-r--r-- 1 root root  3912 12 月 21 13:01 test.o
-rwxr-xr-x 1 root root 13952 12 月 21 13:03 test
[root@localhost cpptest]# ./test 
ljt5

也可胜利生成 test。
采纳此种形式,如果咱们在内部调用一个 func(str,”5″);, 仍然会报错,因为未对 func(string,string)进行实例化调用,没有生成对应的符号。

模板拆散的解决办法:

1、文件 (.h/.cpp) 拆散,在 cpp 中对每种状况进行实例化调用

template<class T1,class T2>
void func(T1 t1,T2 t2)
{cout<<t1<<t2<<endl;}

void func1(string str,int num){func(str,num);
}

void func1(string str1,string str2){func(str1,str2);
}

void func1(string str1,double dx){func(str1,dx);
}

//etc.

2、申明和定义都放到.h 中(STL)
相当于在 cpp 中进行实例化,在.h 中实现申明和定义,然而这个违反了拆散编译的思维。
test.h

#include <iostream>
using namespace std;
template<class T1,class T2>
void func(T1 t1,T2 t2);

template<class T1,class T2>
void func(T1 t1,T2 t2)
{cout<<t1<<t2<<endl;}

参考:https://www.cnblogs.com/downe…

正文完
 0