类模板中成员函数的调用时机
类模板是对一批仅仅成员数据类型不同的类的抽象,基本的概念性东西本章就不再赘述。本章主要探究一下类模板中的成员函数调用时机,下来看一下代码案例。
#include <iostream> using namespace std; class Person1 { public: void showPerson1(){ cout << "show person1" << endl;}; }; class Person2 { public: void showPerson2(){ cout << "show person2" << endl;}; }; // 定义自己的类模板 template <class T> class Myclass { public: // 类模板中的成员函数 void func1(){ obj_p.showPerson1();}; void func2(){ obj_p.showPerson2();}; private: T obj_p; }; int main() { return 0; }上述代码中的main函数中直接返回;我们编译一下如下图:
上述代码编译不会报错。但上述代码中类模板的成员函数中的成员变量obj_p调用了Person1类的成员函数,也调用了Person2类的成员函数,这说明类模板的成员函数在编译时没有调用到成员函数。
接下来我们进一步测试,将main函数改为如下:
int main() { Myclass<Person1> p1; p1.func1(); p1.func2(); return 0; }函数编译结果如下:
上述结果报错的原因是因为Person1类中没有showPerson2的函数。
上述两个结果进一步证明:编译器在编译程序时,对于模板类中的成员变量的类型不确定,因此也就不会检测类模板中的成员函数,当类模板实例化一个对象时,此时该对象的成员变量的类型已确定,在调用对应的成员函数时编译器会确定是否合法。
我们进一步将main函数改成如下:
int main() { Myclass<Person1> p1; p1.func1(); Myclass<Person2> p2; p2.func2(); return 0; }函数编译结果如下:
对上述测试结果的总结:类模板中的成员函数并不是一开始就创建的,在调用时才去创建。
类模板分文件编写
由于上述章节我们知道,类模板中的函数只有在调用时才去创建,这样会导致分文件编写链接不到。接下来举个案例。
如下main.cpp代码:
#include <iostream> #include <string> using namespace std; template<class T1, class T2> class Person { public: Person(T1 name, T2 age); void showPerson(); private: T1 m_name; T2 m_age; }; template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age) { this->m_name = name; this->m_age = age; } template<class T1, class T2> void Person<T1, T2>::showPerson() { cout << "name:" << this->m_name << ", age:" << this->m_age << endl; } int main() { Person<string, int> p1("lijd", 18); p1.showPerson(); return 0; }上述程序编译、运行都没问题,结果如下:
将上述代码分文件编写后,代码结构如下:
// 文件名为person.h #ifndef _PERSON_H_INCLUDED #define _PERSON_H_INCLUDED #include <iostream> #include <string> using namespace std; template<class T1, class T2> class Person { public: Person(T1 name, T2 age); void showPerson(); private: T1 m_name; T2 m_age; }; #endif // _PERSON_H_INCLUDED// 文件名为person.cpp #include "person.h" template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age) { this->m_name = name; this->m_age = age; } template<class T1, class T2> void Person<T1, T2>::showPerson() { cout << "name:" << this->m_name << ", age:" << this->m_age << endl; }// 文件名为main.cpp #include "person.h" int main() { // Person<string, int> p1("lijd", 18); // p1.showPerson(); return 0; }尝试编译结果如下:
分析结果:这是因为上面所说的类模板中的成员函数并不是一开始就创建的,在调用时才去创建。由于main.cpp文件只包含person.h,并没有包含person.cpp,当编译器调用时没有找到函数实现而报错。
解决这种错误的方法有两种:1、直接在文件引用person.cpp,这种方法可以解决,但一般不这样写。2、将person.h中的声明跟person.cpp中的实现全部写在person.hpp中,main函数只要包含person.hpp就可以了,一般默认为hpp文件就是一个类模板文件。
修改后的代码如下:
// 文件名为person.hpp #ifndef _PERSON_HPP_INCLUDED #define _PERSON_HPP_INCLUDED #include <iostream> #include <string> using namespace std; template<class T1, class T2> class Person { public: Person(T1 name, T2 age); void showPerson(); private: T1 m_name; T2 m_age; }; template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age) { this->m_name = name; this->m_age = age; } template<class T1, class T2> void Person<T1, T2>::showPerson() { cout << "name:" << this->m_name << ", age:" << this->m_age << endl; } #endif // _PERSON_HPP_INCLUDED// 文件名为main.cpp #include "person.hpp" int main() { Person<string, int> p1("lijd", 18); p1.showPerson(); return 0; }程序执行及运行结果如下:
本文探讨了类模板中成员函数的调用时机,指出成员函数并非一开始就创建,而是在实例化对象并调用时才确定。通过代码示例展示了类模板实例化时如何调用不同类的成员函数,并解释了由此导致的分文件编写时可能出现的链接错误。解决方案是将模板类的声明和实现放在同一个头文件中,或者在需要使用的地方直接包含实现文件。






1005

被折叠的 条评论
为什么被折叠?



