当前位置: 首页 > news >正文

C++复习笔记8

       泛型编程:编写的是与类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的基础。

       1.函数模板:类型参数化,增加代码复用性。例如对于swap函数,不同类型之间进行交换都需要进行重载,但是函数体不变,就可以体现模板的优越性。

模板参数两种给出方法1.自动类型推导2.显示类型确定

#include<iostream>
using namespace std;//都是进行交换
//不同类型参数的重载代码冗余,复用性低
//模板是将类型当作参数进行传递//函数模板
template< typename T>
void Swap(T& a, T& b)
{cout << typeid(T).name() << endl;T tmp = a;a = b;b = tmp;
}void test01()
{int i1 = 10, i2 = 20;char c1 = 'a', c2 = 'b';double d1 = 1.5, d2 = 5.1;Swap(i1, i2);//自动类型推导Swap<char>(c1, c2);//显示类型指定Swap<double>(d1, d2);cout <<"i1= "  << i1  <<" i2=" <<i2 << endl;cout << "c1= " << c1 << " c2=" << c2 << endl;cout << "d1= " << d1 << " d2=" << d2 << endl;
}void main()
{test01();system("pause");
}

在自动类型推导中,T类型必须一致,不然出现二义性。 

解决方案1:

void test02()
{int a = 10;//4字节double b = 1.23;//8字节Swap(a, (int&)b);//Swap((double&)a, b);//报错 涉及引用修改了原空间范围Swap<int>(a, (int&)b);
}

解决方案2:

template< typename T1, typename T2>
void Swap(T1& a, T2& b)
{cout << typeid(T1).name() << endl;T1 tmp = a;a = b;b = tmp;
}

另一个例子:

#include<iostream>
using namespace std;template<typename T>
T Func(T a, T b)
{T value = a + b;return value;
}void  test01()
{int a = 10;double b = 1.35;Func(a, (int)b);Func((double)a, b);//不修改原空间大小,可以强转Func<int>(a, b);
}void main()
{test01();system("pause");
}

        在调用函数模板时,并不是直接执行函数模板,在编译器底层,模板会根据不同的类型传入生成不同的模板函数。所以母体就是函数模板,实际执行的是模板函数。所以模板看起来比较简洁,但是执行效率不高。

        模板实例化:调用函数模板,生成特定版本函数的过程。隐式实例化->模板类型推导,显式实例化通过<类型>确定。

       注意模板不会进行隐式类型转换,也就是类型的传入不能产生二义性。普通函数支持隐式类型转换。

       当函数模板和普通函数都匹配调用时,会采用最佳匹配原则。

#include<iostream>
using namespace std;template<typename T>
T Func(T a, T b)
{T value = a + b;return vale;
}int Func(int a, int b)
{int value = a + b;return value;
}void test01()
{Func(1, 2);//调上面Func(1.1, 2.2);//调下面Func('a', 'b');//调下面Func<int>('a', 'b');//调下面Func<int>(1, 2);//调下面;Func(1, 2.1);//调上面
}

 类模板:类中的数据类型参数化就可以得到类模板。注意函数模板的每一个成员函数在类外实现时都是函数模板,需要带上template<typename T>,在作用域限定符中也要加上<T>。

c++的类中需要常量可以用这三种方法给出:宏定义、 枚举(私有成员变量)、const常量(私有成员变量)。

#define AAA 8enum 
{ BBB=8};const int CCC = 8;

模板类的参数可以是一个已经实例化的模板类,例如使用vector实现二维数组。

vector<vector<int>> arr;

类模板:实例化时需要指定参数类型,它不能推导类型,利用类名<数据类型> 对象名来实例化。

类模板和函数模板都可以用于处理自定义数据类型,自定义类需要用到运算符重载。

内置类型的零初始化,固定写法,系统自动生成,不会发生隐式类型转换。其实就是赋各种0值。

零初始化也可以用于类模板,用于自定义数据类型。比较灵活。零初始化语法:T 变量名 = T();

调动默认构造函数(或者全缺省构造函数)进行赋值。

#include<iostream>
using namespace std;void main()
{int a = int();char ch = char();double d = double();float f = float();system("pause");
}

 类模板不支持分离编译,类模板的成员函数的创建时机在调用时,分文件编写时链接不到,所以一般通过包含.cpp或者.hpp(声明和定义放一起)的方式来给出。

extern 关键字:让全局变量在同一工程下被不同的.cpp文件外部引入并使用。

STL:标准模板库开个头:

六大组件:容器、算法、仿函数、迭代器、适配器(配接器)、空间配置器。

STL缺点:更新慢、不支持线程安全、追求效率导致内部复杂、存在代码膨胀的问题。但是作为大佬造好的轮子,不会不行!

P.J.版本对应vc6.0    SGI版本对应STL源码剖析。

#include<iostream>
#include<list>
using namespace std;void test01()
{list<int> mylist;for (int i = 0; i < 10; i++){mylist.push_back(i);}for (auto e : mylist){cout << e << "->";}cout << "over." << endl;for (list<int>::iterator it = mylist.begin(); it != mylist.end(); it++){cout << *it << "->";}cout <<"over."<<endl;
}void main()
{test01();system("pause");
}

        

http://www.lryc.cn/news/2830.html

相关文章:

  • RabbitMQ入门
  • 【计算机网络】Linux环境中的TCP网络编程
  • idekCTF 2022 比赛复现
  • jvm的类加载过程
  • VOC数据增强与调整大小
  • Linux 安装jenkins和jdk11
  • Pandas——Series操作【建议收藏】
  • JUC并发编程Ⅰ -- Java中的线程
  • 基于vue-admin-element开发后台管理系统【技术点整理】
  • 【C语言学习笔记】:通讯录管理系统
  • 开关电源环路稳定性分析(10)——OPA和OTA型补偿器传递函数
  • 2.11知识点整理(关于pycharm,python,pytorch,conda)
  • Linux服务器开发-2. Linux多进程开发
  • Excel中缺失数据值的自动填充
  • 路由器刷固件
  • leetcode: Two Sum II - Input Array is Sorted
  • STL——list
  • 实战打靶集锦-004-My-Cmsms
  • c++代码实现我的世界(14)
  • RMQ--区间最值问题(在更)
  • 一篇文章搞懂Cookie
  • 深入解读.NET MAUI音乐播放器项目(二):播放内核
  • 4.SpringWeb
  • C++中的枚举与位域
  • 第19章 MongoDB Limit与Skip方法教程
  • 进程间通信——消息队列
  • OpenMMLab 实战营打卡 - 第 7 课
  • MAC Boook打印长图
  • web3:区块链共识机制系列-POS(Proof of Stake)股权证明算法
  • Linux fork()系统调用流程解析