内容纲要
类模板分文件编写
学习目标:
- 掌握类模板成员函数分文件编写产生的问题以及解决方式
问题:
- 类模板中成员函数创建时机是在调用阶段,导致分文件编写时连接不到
解决:
- 直接包含.cpp 源文件 //主流使用方法2,写为.hpp文件。
- 将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制。
//Person.hpp 文件
#include<iostream>
#include"string"
using namespace std;
class Test {
public:
void setName(string name);
void setAge(int age);
void showTest();
string name;
int age;
};
template <typename T1, typename T2>
class Person {
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
void Test::setAge(int age) {
this->age = age;
}
void Test::setName(string name) {
this->name = name;
}
void Test::showTest() {
cout << "name :" << this->name << "\t age :" << this->age << endl;
}
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
this->m_Age = age;
this->m_Name = name;
}
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
cout << "name :" << this->m_Name << "\t age :" << this->m_Age << endl;
}
//类模板分文件编写.cpp 文件
#include<iostream>
#include "string"
using namespace std;
#include"Person.hpp"
//
//
//template <typename T1,typename T2>
//class Person {
//public:
// Person(T1 name, T2 age);
//
// void showPerson();
//
// T1 m_Name;
// T2 m_Age;
//
//};
//
//template<class T1,class T2>
//Person<T1,T2>::Person(T1 name ,T2 age) {
// this->m_Age = age;
// this->m_Name = name;
//}
//
//
//template<class T1,class T2>
//void Person<T1,T2>::showPerson() {
//
//}
//
//class Test{
//public:
// Test(string name,int age) {
// this->name = name;
// this->age = age;
// }
// string name;
// int age;
//};
void test() {
Person<string,int> p("张三", 11);
p.showPerson();
/*Test test;
test.setAge(18);
test.setName("张三");
test.showTest();*/
}
void main() {
test();
}
Summary
主流编写代码规范一般讲模板类和头文件放在一起,即编写为.hpp 文件,所以,一般看到.hpp 文件就知道里面包含类模板. ( 其实不写成hpp 文件也行,写成h 头文件也是一样的效果,只是hpp 更有辨识度 )
类模板与友元
- 全局函数类内实现 - 直接在类内声明友元即可
- 全局函数类外实现 - 需要提前让编译器知道全局函数的存在。
talk is cheap, show me the Code;
#include<iostream>
#include"string"
using namespace std;
//提前让编译器知道GoodGay这个类的存在
template <class T1,class T2>
class GoodGay;
//类外实现,让编译器先知道这是一个友元模板类的类外实现。
//否则编译器会以为这是一个普通的模板函数。
template<class T1, class T2>
void GolbalFuncFriend2(GoodGay<T1, T2> p)
{
cout << "p.name = " << p.m_Name << "\t p.age = " << p.m_Age << endl;
}
template<class T1,class T2>
class GoodGay {
//1.全局函数类内实现。
friend void GolbalFuncFriend(GoodGay<T1,T2> p) {
//friend void GolbalFuncFriend() { //注意,这里如果没有模板参数的时候,编译器不会报错,但是生成的时候就会报错。(这里有模板类才会被认为是类模板的友元)
cout << "想必你是用GoodGay的类名来调用的吧" << endl;
}
//2.全局函数类外实现.
//2.1加空参数列表
//2,2如果全局函数是类外实现的话,需要让编译器提前知道这个函数的存在。
friend void GolbalFuncFriend2<>(GoodGay<T1, T2> p);
public:
GoodGay(T1 name,T2 age) {
this->m_Name = name;
m_Age = age;
}
private:
T1 m_Name;
T2 m_Age;
};
void main() {
GoodGay<string ,int> p("zhangsan", 11);
//GolbalFuncFriend();如果里面的友元没有写形参,那么编译器不会报错,但是生成时会报错。
//GolbalFuncFriend(p);
GolbalFuncFriend2(p);
}
建议全局函数做类内实现,用法简单,而且编译器可以直接识别。(这一部分听得脑瓜子嗡嗡的)