C++泛型编程

感谢哔哩哔哩UP”开发者LaoJ“,以下是听课记录~

模板是C++实现泛型编程的手段,同一段代码逻辑可以接受多个类型的参数

无论是函数模板还是类模板,在编码后,需要分文件时,将其声明和定义放进.hpp文件中。不要将声明放.h,定义放.cpp,会报错

一、函数模板

对于函数模板,使用不同的类型对其进行实例化时,会生成多个不同的函数

当没有调用函数模板时,不会被实例化(延迟实例化)

1.1、接受类型参数

#include 
#include 
using namespace std;

template 
void Swap(T& a, T& b)
{
	T tmp = a;
	a = b;
	b = tmp;
}
/*允许为特定的数据类型提供定制的实现
 *当类型为int时,调用的是以下实现,而不是函数模板中的实现*/
void Swap(int& a, int& b)
{
	int tmp = a;
	a = 2 * b;
	b = 2 * tmp;
}

int main(void)
{
	int val1 = 10, val2 = 20;
	cout << val1 << " " << val2 << endl;
	/*函数模板有自动推导
	 *Swap(val1, val2)与Swap(val1, val2)等价*/
	Swap(val1, val2);
	cout << val1 << " " << val2 << endl;
	double d1 = 3.14, d2 = 6.78;
	cout << d1 << " " << d2 << endl;
	Swap(d1, d2);
	cout << d1 << " " << d2 << endl;
	return 0;
}

1.2、接受非类型参数作为常量 

#include 
#include 
using namespace std;

template 
void printNTimes(const string& str)
{
	for (int i = 0; i < N; ++i)
		cout << str << endl;
}

int main(void)
{
	string str = "hello world!";
	printNTimes<5>(str);
}

二、类模板

2.1、类模板

类模板的类型参数可以有默认值(默认值从右到左,不能出现右边的没有默认值而左边的有默认值)

类模板没有自动推导的使用方式(在创建类对象时,必须显式说明类型)

/*没有自动推导方式*/
template
clase myclass
{
public:
	myclass(T1 name, T2 age) : name(name), age(age) {}
private:
	T1 name;
	T2 age;
};

myclass obj("lisi", 20);       //正确
myclass obj("lisi", 20);                    //错误,要显示说明类型


/*默认值*/
template    //正确,可以有默认值
template //错误,默认值应该从右到左

2.1.1、模板类在调用时,才会被实例化

#include
using namespace std;

class me
{
public:
	void showme() {
		cout << "This is me" << endl;
	}
};

template 
class myclass
{
public:
	void test() {
        T obj;
        obj.showme();   //未定义
    }
};

int main(void)
{
	myclass obj;
	obj.test();
	return 0;
}

2.1.2、在模板类内声明函数,在类外定义函数

#include
using namespace std;

class me
{
public:
	void showme() {
		cout << "This is me" << endl;
	}
};

template 
class myclass
{
public:
	void test();
};

/*函数在类外进行定义*/
template 
void myclass::test() {
	T obj;
	obj.showme();
}

int main(void)
{
	myclass obj;
	obj.test();
	return 0;
}

2.1.3、当模板类作为函数参数时

#include
#include
using namespace std;

template 
class myclass
{
public:
	myclass(T1 name, T2 age) : name(name), age(age) {}
	void showme() {
		cout << "name:" << name << " " << "age:" << age << endl;
	}
private:
	T1 name;
	T2 age;
};

/*方法一:确定具体的类型传入*/
void func1(myclass obj) 
{
	obj.showme();
}

/*方法二:参数模板化*/
template 
void func2(myclass obj) 
{
	obj.showme();
}

/*方法三:将类模板化*/
template 
void func3(T& obj) 
{
	obj.showme();
}

int main(void) 
{
	myclass obj("lisi", 20);
	func1(obj);
	func2(obj);
	func2(obj);
	return 0;
}

2.2、类模板与继承

#include 
using namespace std;

/*基类是模板类*/
template 
class Base {
public:
    Base(T value) : data(value) {}
    void show() {
        cout << "Base data: " << data << endl;
    }
protected:
    T data;
};

/*情况一:派生类不是模板类*/
//方法一:派生类继承模板基类的特化版本(例如 int)
class DerivedInt : public Base {
public:
    DerivedInt(int value) : Base(value) {}  //在此处,调用了Base类的构造函数
    void display() {
        cout << "DerivedInt data: " << data << endl;
    }
};
//方法二:派生类继承模板基类(仍然是模板)
template 
class DerivedTemplate : public Base {
public:
    DerivedTemplate(T value) : Base(value) {}
    void display() {
        cout << "DerivedTemplate data: " << this->data << endl;
    }
};

/*情况二:派生类是模板类*/
template 
class Derived : public Base {
public:
    Derived(T baseValue, U derivedValue) : Base(baseValue), extraData(derivedValue) {}
    void display() {
        cout << "Base data: " << this->data << ", Derived data: " << extraData << endl;
    }
private:
    U extraData;
};

int main() {
    /*对于情况一*/
    DerivedInt obj1(10);
    obj1.show();
    obj1.display();

    DerivedTemplate obj2(3.14);
    obj2.show();
    obj2.display();

    /*对于情况二*/
    Derived obj3(10, 3.14);
    obj3.show();     // 调用基类方法
    obj3.display();  // 调用派生类方法

    return 0;
}

2.3、友元函数与模板类

#include 
#include 
using namespace std;

// 前向声明模板类和函数print
template 
class Base;
template 
void print(Base& obj);

template 
class Base {
public:
    Base(T1 name, T2 age) : name(name), age(age) {}
    /*在类内定义友元函数*/
    friend void show(Base& obj) {
        cout << "show:" << endl;
        cout << "name:" << obj.name << " " << "age:" << obj.age << endl;
    }
    friend void print(Base& obj);
private:
    T1 name;
    T2 age;
};

/*在类外定义友元函数
 *一、需要向前声明模板类和友元函数
 *二、在类中声明友元函数
 *三、在类外定义友元函数*/
template 
void print(Base& obj) {
    cout << "print: " << endl;
    cout << "name:" << obj.name << " " << "age:" << obj.age << endl;
}

int main(void) {
    Base obj("lisi", 20);
    show(obj);
    print(obj);
    return 0;
}

你可能感兴趣的:(C++,Primer第五版——读书笔记,c++,开发语言)