当前位置:首页 > 谈天说地

c++类模板的使用(c++入门代码)

34资源网2022-02-12704

例子1 复数类—-所有函数写的类的内部

#include<iostream>
using namespace std;
template<typename T>
class Complex
{
	firend ostream & operator<<(ostream &out, Complex &c3)
	{
		cout << "a:" << " + " << "b:" << c3.b << endl;
		return out;
	}
public:
	Complex(T a=0,T b=0);
	{
		this->a = a;
		this->b = b;
	}
	Complex  operator+(Complex &c2)
	{
		Complex tmp(a + c2.a, b + c2.b);
		return tmp;
	}
	void printComplex()
	{

		cout << "a:" << a << "b:" << b << endl;
     }
	
private:
	T  a;
	T  b;
};
//运算符重载的正规写法,重载<<  >>只能用友员函数,其他运算符重载,都要写成成员函数,不要滥用友员函数

void main()
{
//需要把模板类进行具体化以后,才能定义对象,c++编译器要分配内存
	Complex<int>    c1(1,2);
	Complex <int>   c2(3, 4);
	Complex<int>    c3=c1+c2;
	cout << c3 << endl;
	system("pause");
	return;
}

例子2 复数类—-所有函数写的类的外部,但在一个cpp里

#include<iostream>
using namespace std;
template<typename T>
class Complex
{
	firend Complex  MySub<<(Complex &c1, Complex &c2)
	{
		Complex tmp(a + c2.a, b + c2.b);
		return tmp;
	}
	firend ostream & operator<< <T> (ostream &out, Complex &c3);
	
public:

	Complex(T a, T b)
		Complex  operator+(Complex &c2)
		void printComplex();

private:
	T  a;
	T  b;
};
template<typename T>//构造函数的实现,写在了类的外部
Complex<T>::Complex(T a,T b)
{
	this->a = a;
	this->b = b;
}
template<typename T>
void  Complex::printComplex()
{

	cout << "a:" << a << "b:" << b << endl;
}
template<typename T>
Complex<T> Complex<T>::operator+(Complex<T> &c2)//成员函数实现+运算符重载
{
	Complex tmp(a + c2.a, b + c2.b);
	return tmp;
}
template<typename T>
ostream & operator<<(ostream &out, Complex<T>&c3)//友员函数实现运算符重载
{
	cout << "a:" << " + " << "b:" << c3.b << endl;
	return out;
}
void main()
{
	Complex<int>    c1(1, 2);
	Complex <int>   c2(3, 4);
	Complex<int>    c3 = c1 + c2;
	cout << c3 << endl;
	system("pause");
	return;
}

归纳以上的介绍,可以这样使用.声明类模板

1)先写出一个实际的类.由于其语义明确,含义清楚,一般不会出错.

2)将此类中准备改变的类型名(如int 要改为char)改用一个自己指定的虚拟类型名字

3)在类声明前加入一行,格式为:

template<class 虚拟类型函数>//注意本行末尾无分号

4)用类模板定义对象使用以下形式:

类模板名<实际类型名>对象名

类模板名<实际类型名>对象名(实参列表)

如:

Compare<int> cmp;

Compare<int> cmp(3,4);

5)如果在类模板外定义成员函数,应该写成类模板形式:

template<class 虚拟类型函数>

函数类型 类模板名<虚拟函数参数>::成员函数名(参数形参列表)(……)

关于类模板的几点说明

1)类模板的类型参数可以有一个或多个,每个类型前面都必须加class,

如:

template<class T1,class T2>

class someclass

{……}

定义对象时分别带入实际的类型名,如;

someclass<int,double>obj;

2)和使用类一样,使用类模板时要注意其作用域,只能在其有效作用域内用它定义对象.

3)模板可以有层次,一个类模板可以作为基类,派生出派生类的模板,有关这方面的知识实际应用比较少,感兴趣的可以自行查阅.

类模板中的ststic关键字

从类模板比例实例化的每个模板类都有自己的类模板数据成员,该模板类的所有对象共享一个

ststic数据成员.

和非模板类的ststic数据成员一样,模板类的ststic数据成员,也应该在文件范围定义和初始化.

每个模板类都有自己的类模板和ststic数据成员副本.

例子

#include<iostream>
using namespace std;
template<typename T>
class AA
{
public:
	static T m_a;
private:

};


class AA1
{
public:
	static int m_a;
private:

};
template<typename T>
int  AA1::m_a = 0;

class AA2
{
public:
	static char m_a;
private:

};
char  AA2::m_a = 0;

void main()
{
	AA<int> a1, a2, a3;
	a1.m_a = 10;
	a2.m_a++;
	a3.m_a++;
	cout << AA<int>::m_a << endl;


	AA<char> b1, b2, b3;
	b1.m_a = 'a';
	b2.m_a++;
	b2.m_a++;
	cout << AA<char>::m_a << endl;
	//m_a应该是每一种类型的类,使用自己的m_a
	system("pause");
	return;

}

异常问题

一、为什么要有异常——WHY?

1.通过返回值表达错误

像malloc会返回0或1.

局部对象都能正确的析构

层层判断返回值,流程繁琐

例子:

#include <iostream>
#include <cstdio>
using namespace std;
int func3 (void) {
FILE* fp = fopen ("none", "r");//fopen失败会返回控指针NULL。
if (! fp)
return -1;
// ...
fclose (fp);
return 0;
}
int func2 (void) {
if (func3 () == -1)
return -1;
// ...
return 0;
}
int func1 (void) {
if (func2 () == -1)
return -1;
// ...
return 0;
}
int main (void) {
//层层判断返回值
if (func1 () == -1) {
cout << "执行失败!改天再见!" << endl;
return -1;
}
// ...
cout << "执行成功!恭喜恭喜!" << endl;
return 0;
}

2.通过setjmp/longjmp远程跳转

一步到位进入错误处理,流程简单

局部对象会失去被析构的机会

例子:

#include <iostream>
#include <cstdio>
#include <csetjmp> //标c的函数,跳转
using namespace std;
jmp_buf g_env; //jmp是专门为c量身定造的,有类的情况不适用,会跳转,因为不执行右括号,局部对象失去执行析构的机会,不会调用析构函数,会造成内存泄露
class A {
public:
A (void) {
cout << "A构造" << endl;
}
~A (void) {
cout << "A析构" << endl;
}
};
void func3 (void) {
A a;
FILE* fp = fopen ("none", "r");
if (! fp)
longjmp (g_env, -1); //(没有定义类的时候)这个时候是的g_env变为-1,但是不在这返回,在main函数的setjmp处返回
// ...
fclose (fp);
}
void func2 (void) {
A a;
func3 ();
// ...
}
void func1 (void) {
A a;
func2 ();
// ...
}
int main (void) {
if (setjmp (g_env) == -1) { //(没有定义类的时候)第一次到这,genv是0,所以执行下面的func1(),执行了后在fun3中的longjmp处在缓冲区使得g_env变为1,并在这使g_env返回
cout << "执行失败!改天再见!" << endl;
return -1;
}
func1 ();
// ...
cout << "执行成功!恭喜恭喜!" << endl;
return 0;
}

———————————————————————

3.异常处理

局部对象都能正确的析构

一步到位进入错误处理,流程简单

———————————————————————

二、异常的语法——WHAT?

1.异常的抛出

throw 异常对象;

异常对象可以是基本类型的变量,也可以是类类型的对象。

当程序执行错误分支时抛出异常。

2.异常的捕获

try {

可能抛出异常的语句块;

}

catch (异常类型1 异常对象1) {

处理异常类型1的语句块;

}

catch (异常类型2 异常对象2) {

处理异常类型2的语句块;

}

…

catch (…) {

处理其它类型异常的语句块;

}

异常处理的流程,始终沿着函数调用的逆序,依次执行右花括号,直到try的右花括号,保证所有的局部对象都能被正确地析构,然会根据异常对象的类型,匹配相应的catch分支,进行有针对性的错误处理。

例子:
#include <iostream>
#include <cstdio>
using namespace std;
class A {
public:
A (void) {
cout << "A构造" << endl;
}
~A (void) {
cout << "A析构" << endl;
}
};
void func3 (void) {
A a;
FILE* fp = fopen ("none", "r");
if (! fp) { //如果不发生异常,不执行throw,直接执行throw后面的语句
cout << "throw前" << endl;
throw -1; //如果有异常,throw之后的语句不执行,直接右括号
cout << "throw后" << endl;
}
cout << "文件打开成功!" << endl;
// ...
fclose (fp);
}
void func2 (void) {
A a;
cout << "func3()前" << endl;
func3 (); //如果有异常,则直接右括号
cout << "func3()后" << endl;
// ...
}
void func1 (void) {
A a;
cout << "func2()前" << endl;
func2 (); //有异常,直接右括号
cout << "func2()后" << endl;
// ...
}
int main (void) {
try {
cout << "func1()前" << endl;
func1 (); //之后进入func1,先创建a,执行构造,再进入func2,又创建a,执行构造,再进入func3,又创建a,执行构造,然后执行throw,抛出-1;结束func3,释放func3中的a,调用析构,然后func2结束,释放func2的a,调用析构,然后func1结束,释放func1的a,调用析构。然后直接到try的右花括号,然后执行异常处理,根据异常对象的类型匹配相应的catch,这里是“执行失败”。
cout << "func1()后" << endl;
}
catch (int ex) {
if (ex == -1) {
cout << "执行失败!改天再见!" << endl;
return -1;
}
}
// ...
cout << "执行成功!恭喜恭喜!" << endl;
return 0;
}

版权声明:34楼发布

本文链接:https://www.34l.com/post/7550.html

分享给朋友:

相关文章

调整心态温暖哲理经典语录,看这些语录能够调整心态

调整心态温暖哲理经典语录,看这些语录能够调整心态

取得成功是他人不成功时仍在坚持不懈。若自身不作出一点外貌,别人想拉你一把都不知道你的手在哪儿。直至你不会再找我聊,直至你找不着我,直至最终,你一直在某一瞬间猛地想起我。但是,那个时候,被你弄丢的我就确实早已没有了,也再不想要你再找回家了。理…

工具人是什么意思,工具人是什么梗?

工具人是什么意思,工具人是什么梗?

最近网络上面出现比较多的一个词语就是“工具人”,那么,什么样的人会将他形容成是工具呢?这个是让网友们觉得比较的好奇的,主要是指的什么?在微博上面经常看到有网络语工具人这样的表达,所以引起了很多网友的关注,想要了解这个词语,那么工具人是什么意…

联想新手机什么时候上市(联想2021即将上市新款笔记本)

联想新手机什么时候上市(联想2021即将上市新款笔记本)

11月8日,联想中国区手机业务部总经理发布了一则新机预告:摩托罗拉edge X的发布已进入倒计时阶段,在骁龙898处理器即将发布之际预告新机,很大可能预示着首发权已到手。…

融资丨「奕斯伟计算」完成25亿元C轮融资,目标物联网芯片领域全球领导者

融资丨「奕斯伟计算」完成25亿元C轮融资,目标物联网芯片领域全球领导者

创业邦获悉,12月1日,AIoT芯片与解决方案提供商北京奕斯伟计算技术有限公司(以下简称:奕斯伟计算)宣布完成25亿元人民币C轮融资,由金石投资和中国互联网投资基金联合领投,尚颀投资、国开科创、华新投资等跟投,老股东 IDG、君联资本、刘益…

win10纯净安装版推荐(windows10纯净版安装步骤)

win10纯净安装版推荐(windows10纯净版安装步骤)

今天跟大家介绍windows10的一个非常简洁的版本:Win10 LTSC版。 这个版本的亮点有很多,最突出的就是简洁。比起普通win10系统,它没有那些多余的功能。例如小娜助手、edge浏览器、还有应用商店,这些功能想必大部分用户都用不上…

网络信息安全方案设计(计算机网络安全与防范论文)

企业网络安全的重要性 随着网络技术的飞速发展,如今网络无所不在地影响着我们工作与生活,我们对网络的依赖越来越强。而伴随着网络技术的发展,网络安全问题也出现在我们眼前。可以说,有网络的地方就存在网络安全隐患。网络安全的含义具体是什么呢?国际标…