C++ 提高篇

提高篇

类型转换:

  • static_cast 用于内置数据类型、具有继承关系的指针类型、具有继承关系的引用转换
  • dynamic_cast 通常在基类和及派生类转换时使用
  • const_cast 主要针对const和非const的转换
  • reinterpret_cast 用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整型数

示例:

#include<iostream>
using namespace std;

class Building
{
    
    };

class Animal
{
    
    

};

class Cat :public Animal
{
    
    

};
//1、static_cast 用于内置数据类型、具有继承关系的指针类型、具有继承关系的引用转换
void _01Test01()
{
    
    
	//用于内置数据类型
	int a = 97;
	char c = static_cast<char>(a);
	cout << c << endl;

	//用于具有继承关系的指针
	Animal* animal1 = NULL;
	Cat* cat1 = static_cast<Cat*>(animal1);
	Cat *cat2=NULL;
	Animal *animal2 = dynamic_cast<Animal*>(cat2);

	//用于具有继承关系的引用
	Animal ani;
	Animal& animal11 = ani;
	Cat& cat11 = static_cast<Cat&>(animal11);
	Cat ca;
	Cat& cat22 = ca;
	Animal& animal22 = static_cast<Animal&>(cat22);

}

//2、dynamic_cast   通常在基类和及派生类转换时使用,在转换前会进行对象类型检查
void _01Test02()
{
    
    
	//父类指针转为子类指针会造成访问错误
	//子类指针可以转为父类指针
	Cat* cat = NULL;
	Animal* animal = dynamic_cast<Animal*>(cat);
}

//3、const_cast 主要针对const和非const的转换
void _01Test03()
{
    
    
	//基本数据类型
	int a = 10;
	const int& b =a;//非const转化为const
	int& c = const_cast<int &>(b);//const转化为非const

	c = 20;
	cout << "a:" << a << endl;
	cout << "b:" << b << endl;
	cout << "c:" << c << endl;

	//指针
	int* p1=NULL;
	const int* p2 = p1;//非const转化为const
	int* p3 = const_cast<int*>(p2);//const转化为非const

}

//4、reinterpret_cast  强制类型转换   用于进行没有任何关联之间的转换,比如一个字符指针转换为一个整型数
typedef int(*FUN1)(int, int);
typedef int(*FUN2)(int,char);
void _01Test04()
{
    
    
	//1、无关类型的指针都可进行转换
	Building* build = NULL;
	Animal* animal = reinterpret_cast<Animal*>(build);
	
	//2、函数指针转换
	FUN1 fun1=NULL;
	FUN2 fun2 = reinterpret_cast<FUN2>(fun1);
}

//补充1:函数指针
int sum(int a, int b)
{
    
    
	return a + b;
}
typedef int (*FUNC1)(int, int);//声名函数指针
typedef int (FUNC2)(int, int);//声名函数指针
void _01Test05()
{
    
    
	
	FUNC1 func1=sum;
	FUNC2* func2 = sum;

	//直接申明
	void (*b[10])(void(*)());
	void(*F)(void(*)());
	F = NULL;
	b[0] = F;

	//通过typedef重命名声名
	typedef void(*F1)();
	typedef void(*Funb)(F1);
	Funb bb[10];
	bb[0] = F;
}

//补充2:回调函数
void mySum(int n)
{
    
    
	if (n <= 0)
	{
    
    
		cout << "请输入一个正确的数" << endl;
		return;
	}
	int sum=0;
	for (int i = 0; i <= n; i++)
	{
    
    
		sum += i;
	}
	cout << "从1到" << n << "之和为:" << sum << endl;
}

void callback_int(int n, void(*p)(int))
{
    
    
	return p(n);
}

void _01Test06()
{
    
    
	int n = 100;
	callback_int(n, mySum);
}

void main()
{
    
    
	//_01Test01();
	//_01Test03();
	_01Test06();
}

异常

示例:

#include<iostream>
using namespace std;

//异常基本语法
int divide(int x, int y)
{
    
    
	if (y == 0)
	{
    
    
		throw y;//抛异常
	}
	return x / y;
}

void _02Test01()
{
    
    
	//试着捕获异常
	try
	{
    
    
		divide(10, 0);
	}
	catch (int e)//异常时根据抛出的类型来匹配
	{
    
    
		cout << "除数为" << e << "!" << endl;
	}
}

void main()
{
    
    
	_02Test01();
}

栈解旋

概念:

  • 异常被抛出后,从进入try块起,到异常被抛出前,这器件在栈上的所有对象,都会别被自动析构,析构的顺序和构造顺序相反,这一过程称之为栈的解旋。

示例:

#include<iostream>
using namespace std;

//栈解旋
class Person
{
    
    
public:
	Person()
	{
    
    
		cout << "构造函数调用" << endl;
	}
	~Person()
	{
    
    
		cout<< "析构函数调用" << endl;
	}
};

int myDivide(int a, int b)
{
    
    
	Person p1, p2;
	if (b == 0)
	{
    
    
		throw b;
	}
	return a / b;
}

void  _03Test01()
{
    
    
	try
	{
    
    
		
		myDivide(10, 0);

	}
	catch (int w)
	{
    
    
		cout << "捕获异常" << endl;
	}
	
}

void main()
{
    
    
	_03Test01();
	//先析构后捕获异常
}

异常接口说明

#include<iostream>
using namespace std;

//异常接口说明
//只能抛出int, float, char三种类型的异常
void func1() throw(int, char, float)
{
    
    
	throw "abc";//报错 异常未处理
}

//不能抛出任何异常
void func2() throw()
{
    
    
	throw -1;
}

//可以抛出任何异常
void func3()
{
    
    
	
}

void _04Test01()
{
    
    
	try
	{
    
    
		func1();
		func2();
	}
	catch (char *c)
	{
    
    
		cout << c << endl;
	}
	catch (int e)
	{
    
    
		cout << e;
	}
	catch (...)//抛出所有异常
	{
    
    
		cout << "异常类型不确定" << endl;
	}
}

void main()
{
    
    
	_04Test01();
}

自定义异常和生命周期

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

//自定义异常类型
class MyException
{
    
    
public:
	char* m_Error;

public:
	MyException(const char* str)
	{
    
    
		cout << "构造函数的调用" << endl;
		this->m_Error = new char[strlen(str) + 1];
		strcpy(this->m_Error, str);
	}


	MyException(const MyException& e)
	{
    
    
		cout << "拷贝构造函数的调用" << endl;
		this->m_Error = new char[strlen(e.m_Error) + 1];
		strcpy(this->m_Error, e.m_Error);
	}

	MyException& operator=(const MyException& e)
	{
    
    
		cout << "赋值构造函数的调用" << endl;
		if (this != NULL)
		{
    
    
			delete this;
		}
		this->m_Error = new char[strlen(e.m_Error) + 1];
		strcpy(this->m_Error, e.m_Error);
		return *this;
	}

	~MyException()
	{
    
    
		cout << "析构函数的调用" << endl;
		if (this->m_Error != NULL)
		{
    
    
			delete this->m_Error;
		}
	}

	void what()
	{
    
    
		cout << this->m_Error << endl;
	}
};

void fun1()
{
    
    
	throw MyException("自定义异常");
}

void fun2()
{
    
    
	throw  new MyException("自定义异常");
}

void _05Test01()
{
    
    
	//1、捕获异常对象  通过拷贝构造函数调用 将异常复制一份给e
	try
	{
    
    
		fun1();
	}
	catch (MyException e)
	{
    
    
		e.what();
	}
	
	//2、捕获异常对象引用 只会执行一次构造函数和析构函数
	cout << "---------------------------" << endl;
	try
	{
    
    
		fun1();
	}
	catch (MyException &e)
	{
    
    
		e.what();
	}
	
	//3、捕获异常对象的指针 需要new一个MyException 并手动释放
	cout << "---------------------------" << endl;
	try
	{
    
    
		fun2();
	}
	catch (MyException* e)
	{
    
    
		e->what();
		delete e;
	}
}

void main()
{
    
    
	_05Test01();
}

绑定适配器

功能:

  • 将二元函数对象转变为一元函数对象

bind1st

  • 将参数绑定为函数对象的第一个参数(这里的参数指的是额外参数,而不是容器中的元素)

bind2nd

  • 将参数绑定为函数对象的第二个参数

示例:

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

//绑定适配器
//bind1st - 将参数绑定为函数对象的第一个参数(这里的参数指的是额外参数,而不是容器中的元素)
//bind2nd - 将参数绑定为函数对象的第二个参数
class MyPrint:public binary_function<int,int,void>
{
    
    
public:
	void operator()(int num1,int num2) const
	{
    
    
		cout << "num1=" << num1 << "  num2=" << num2 <<"   结果为:" <<num1+num2<< endl;
	}
};

void _03Test01()
{
    
    
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);
	}
	for_each(v.begin(), v.end(), bind1st( MyPrint(),100));
	cout << "--------------------------------" << endl;
	for_each(v.begin(), v.end(), bind2nd( MyPrint(),100));
}

void main()
{
    
    
	_03Test01();
}

取反适配器

功能:

  • 将谓词进行取反操作

not1: 对一元谓词取反
not2: 对二元谓词取反

示例:

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

//取反适配器
//not1:对一元谓词取反
//not2:对二元谓词取反

class MyPrint
{
    
    
public:
	void operator()(int num)
	{
    
    
		cout << num << "  ";
	}
};
//1、not1:对一元谓词取反
class MyGreater5 :public unary_function<int, bool>
{
    
    
public:
	bool operator()(int num)const
	{
    
    
		return num > 5;
	}

};

void _04Test01()
{
    
    
	srand((unsigned int)time(NULL));
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
    
    
		int random = rand() % 10;
		v.push_back(random);
	}

	vector<int>::iterator it1= find_if(v.begin(), v.end(), MyGreater5());
	cout << *it1 << endl;

	vector<int>::iterator it2 = find_if(v.begin(), v.end(),not1( MyGreater5()));
	cout << *it2 << endl;
}


//2、not2:对二元谓词取反
class MyGreater :public binary_function<int, int, bool>
{
    
    
public:
	bool operator()(int num1, int num2) const
	{
    
    
		return num1 > num2;
	}
};

void _04Test02()
{
    
    
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
    
    
		int random = rand() % 100;
		v.push_back(random);
	}
	sort(v.begin(), v.end(), MyGreater());
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;

	sort(v.begin(), v.end(), not2( MyGreater()));
	for_each(v.begin(), v.end(), MyPrint());
	cout << endl;
}

void main()
{
    
    
	//_04Test01();
	_04Test02();
}

仿函数适配器

功能:

  • 把普通函数转成函数对象

函数原型:

  • ptr_fun(普通函数名);

示例:

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
//仿函数适配器
void myPrint(int num1,int num2)
{
    
    
	cout << "num1=" << num1 << "  num2=" << num2 << "   结果为:" << num1 + num2 << endl;
}

void _05Test01()
{
    
    
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
    
    
		v.push_back(i);
	}

	//ptr_fun(myPrint)将普通函数myPrint转化成一个函数对象 
	//再用bind2nd将myPring函数的第二个参数与100绑定
	for_each(v.begin(), v.end(),bind2nd( ptr_fun(myPrint),100));
}

void main()
{
    
    
	_05Test01();
}

猜你喜欢

转载自blog.csdn.net/qq_60406853/article/details/125406516