2020-02-19 C++提高编程02-基本框架

1.3类模板

1.3.1类模板语法

作用:建立一个通用类,类中的成员 数据类型可以不具体指定,用一个虚拟的类型来代表;

语法: 

template<class T>

解释:

template :声明创建模板

class/typename :表明其后面的符号是一种数据类型

T  :通用数据类型,通常为大写字母

示例:

template<class NameType,class AgeType>

class Person

{

public:

Person(NameType name, AgeType age)

{

this->m_Name = name;

this->m_Age = age;

}

NameType m_Name;

AgeType m_Age;

};

1.3.2类模板与函数模板区别

1.类模板没有自动类型推导的使用方式;

2.类模板在模板参数列表中可以有默认参数;

示例:

template<class NameType, class AgeType=int>

class Person

{

public:

Person(NameType name, AgeType age)

{

this->m_Name = name;

this->m_Age = age;

}

NameType m_Name;

AgeType m_Age;

};

void test01()

{

//无法使用自动类型推导

//Person p("Mike", 20);//error

Person<string,int>p("Mike", 20);

}

void test02()

{

Person<string>p("Mike", 20);//ok 因为模板参数列表设置了默认参数

}


1.3.3类模板中成员函数创建时机

类模板中成员函数和普通类中成员函数创建时机是有区别的:

1.普通类中成员函数一开始就可以创建;

2.类模板中成员函数在调用时才创建;

示例:

class Person1

{

public:

void showPerson1()

{

cout << "showPerson1()" << endl;

}

};

class Person2

{

public:

void showPerson2()

{

cout << "showPerson2()" << endl;

}

};

template <class T>

class MyClass

{

public:

T obj;

//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成

void func1()

{

obj.showPerson1();

}

void func2()

{

obj.showPerson2();

}

};

void test01()

{

MyClass<Person1> m;

m.func1();

//m.func2();//error

//编译会出错,说明函数调用才会去创建成员函数

}

1.3.4类模板对象做函数参数

要点:类模板实例化出的对象,向函数传参的方式

一共有三种传入方式:

1.指定传入的类型  ---直接显示对象的数据类型

2.参数模板化    ---将对象中的参数变为模板进行传递

3.整个类模板化    ---将这个对象类型 模板化进行传递、

示例:

template <class T1, class T2>

class Person

{

public:

Person(T1 name, T2 age)

{

this->m_Name = name;

this->m_Age = age;

}

void showPerson()

{

cout << "name: " << this->m_Name << endl

<< "age: " << this->m_Age << endl;

}

T1 m_Name;

T2 m_Age;

};

//1.指定传入类型

void printPerson1(Person<string, int> &p)

{

p.showPerson();

}

void test01()

{

Person<string, int> p("Mike", 20);

printPerson1(p);

}

//2.参数模板化

template <class T1, class T2>

void printPerson2(Person<T1, T2> &p)

{

p.showPerson();

cout << "type of T1: " << typeid(T1).name() <<endl

<< "type of T2: " << typeid(T2).name() << endl;

}

void test02()

{

Person<string, int> p("Jack", 22);

printPerson2(p);

}

//3.这个类模板化

template <class T>

void printPerson3(T &p)

{

p.showPerson();

cout << "type of T: " << typeid(T).name() << endl;

}

void test03()

{

Person<string, int> p("Mary", 18);

printPerson3(p);

}

总结:

1.通过类模板创建的对象,可以有三种方式向函数中进行传参;

2.第一种指定传入类型 使用的比较广泛;

1.3.5类模板与继承

1.当子类继承的父类是一个类模板时,子类在声明时,要指定出父类中T的类型;

2.如果不指定,编译器无法给子类分配内存;

3.如果想要灵活指定出父类中T的类型,子类也需要变为类模板;

示例:

template <class T>

class Base

{

public:

T m;

};

class Son//:public Base//error 必须要知道父类中T类型,才能继承给子类

:public Base<int>{};

//如果想要灵活指定出父类中T的类型,子类也需要变为类模板

template <class T1,class T2>

class Son2:public Base<T2>

{

public:

T1 obj;

};

void test02()

{

Son2<int,char> s2;

}

总结:如果父类是类模板,子类需要指定出父类中T的数据类型

1.3.6类模板成员函数类外实现

示例:

template<class T1,class 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_Name = name;

this->m_Age = age;

}

template<class T1, class T2>

void Person<T1, T2>::showPerson()

{

cout << "name: " << this->m_Name << endl

<< "age: " << this->m_Age << endl;

}

总结:

1.函数实现体前需要声明是模板;

2.在类名之后加模板参数列表;

1.3.7类模板分文件编写

问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到

解决:

1.直接包含.cpp源文件;

2.将声明和实现写到同一个文件中,并更改后缀名为 .hpp (约定名称,而非强制)

注:主要采用第二种,将类模板成员函数写到一起,并更改后缀为.hpp

示例:

1.person.hpp文件

#pragma once

#include <iostream>

#include <string>

using namespace std;

template<class T1, class 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_Name = name;

this->m_Age = age;

}

template<class T1, class T2>

void Person<T1, T2>::showPerson()

{

cout << "name: " << this->m_Name << endl

<< "age: " << this->m_Age << endl;

}

2.实现文件

#include "person.hpp"

...

1.3.8类模板与友元

要点:掌握类模板配合友元函数的类内和类外实现

全局函数类内实现-直接在类内声明友元即可;

全局函数类外实现-需要提前让编译器知道全局函数的存在;

示例:

1.类内实现

template<class T1, class T2>

class Person

{

friend void printPerson(Person<T1, T2> p)

{

cout << "name: " << p.m_Name << endl

<< "age: " << p.m_Age << endl;

}

public:

Person(T1 name, T2 age)

{

this->m_Name = name;

this->m_Age = age;

}

private:

T1 m_Name;

T2 m_Age;

};

2.类外实现

//提前让编译器知道Person类存在

template<class T1, class T2>

class Person;

//提前让编译器知道这个全局函数的存在

//函数模板声明

template<class T1, class T2>

void printPerson2(Person<T1, T2> p)

{

cout << "name: " << p.m_Name << endl

<< "age: " << p.m_Age << endl;

}

template<class T1, class T2>

class Person

{   

    //error 普通函数声明 并非函数模板声明

//friend void printPerson2(Person<T1, T2> p);

//如果全局函数是类外实现,需要让编译器提前知道这个函数的存在

friend void printPerson2<>(Person<T1, T2> p);

public:

Person(T1 name, T2 age)

{

this->m_Name = name;

this->m_Age = age;

}

private:

T1 m_Name;

T2 m_Age;

};

总结:建议全局函数做类内实现,用法简单,而且编译器可以直接识别;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352