当前位置:网站首页>类模板剖析
类模板剖析
2022-07-22 10:27:00 【码农诗人】
类模板中成员函数的调用时机
类模板是对一批仅仅成员数据类型不同的类的抽象,基本的概念性东西本章就不再赘述。本章主要探究一下类模板中的成员函数调用时机,下来看一下代码案例。
#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; }
程序执行及运行结果如下:
边栏推荐
- Kotlin学习三:集合与Lambda
- Leetcode 32. longest valid bracket
- Flutter development (XXXI): flutter starts the white screen
- Fluent 2 Advanced (IX): fijkplayer plays videos and card effects
- Elastic Search 学习入门之核心概念(四)
- The problem of overwriting array when pushing
- 【C】从内存出发理解C语言变量作用域与生命周期
- Neo4j安装教程
- Fluent 2 Advanced (III): imitate BiliBili, login and register
- 优博讯助力深圳打造全球“鸿蒙欧拉之城”
猜你喜欢
网站别黑了怎么解决?如何处理网站被黑问题详解
使用CSDN-markdown编辑器入门
Fluent 2 Advanced (IV): Based on navigator 2.0 packaging
ping: www.baidu. Com: unknown name or service reason analysis
为什么memset不能将数组元素初始化为1?
dns劫持如何完美修复?dns被劫持如何解决如何完美修复
appstore 上传屏幕快照尺寸
记一次win10安装cupy的失败经历(附 cupy与numpy对比)
求N!后面有多少个0
RetinaNet:Focal Loss for Dense Object Detection
随机推荐
Kotlin学习三:页面的常用写法
AttributeError: module ‘tensorflow.keras.utils‘ has no attribute image_dataset_from_directory——解决方法
dns被劫持了怎么处理 5种方法教你处理
将一些转义字符替换为指定标准的字符
Leetcode 32. longest valid bracket
网站别黑了怎么解决?如何处理网站被黑问题详解
Flutter 2进阶(一):Flutter实用技巧
2017年终总结
RRPN:Arbitrary-Oriented Scene Text Detection via Rotation Proposals
euler五十讲(一)
NC4 judge whether there is a ring in the linked list
Flutter 2进阶(六):回调函数的使用
Error reported by Xcode compiling pod third-party library
开幕在即 | “万物互联,使能千行百业”2022开放原子全球开源峰会OpenAtom OpenHarmony分论坛
When the appsstore transporter uploads, it is stuck in the process of verifying the problem
dns 劫持什么意思、dns 劫持原理及几种解决方法
ES6 usage
Flutter开发(三十二):Flutter屏幕适配
spark中使用Accumulator累加器使用和注意事项
Liangning product course learning