C++笔记(Ⅵ_模板)

友元函数和友元类

  • 函数的定义方式:全局函数或者成员函数
    定义为友元函数或者类,可以任意访问其定义所在的那个类的成员函数和变量
  • 全局友元函数:
    使用关键字friend
//例子
class Coordinate
{
	friend void printXY(Coordinate &c);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//对于上述全局友元函数的使用方法
//1.直接访问私有成员
void printXY(Coordinate &c)
{
	cout<<c.m_iX<<c.m_iY;
}
//2.传入对象名而非地址
int main(void)
{
	Coordinate coor(3,5);
	printXY(coor);
	return 0;
}
  • 友元成员函数:
//例子,将一个类的成员函数声明为另外一个类的友元
class Coordinate
{	
	friend void Circle::printXY(Coordinate &c);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//对于友元成员函数的使用
class Circle
{
public:
	void printXY(Coordinate &c)
	{
	  cout<<c.m_iX<<c.m_iY;
	}
};
int main(void)
{
	Coordinate coor(3,5);
	Circle circle;
	circle.printXY(coor);
	return 0;
}
  1. 友元函数的风险在于破坏了数据的封装型,在友元函数中改变了数据的值,也不易察觉。
  2. 除非有特殊需要,并不建议大家处处使用友元。
  • 友元类:
class Circle;
class Coordinate
{
	friend Circle;
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//circle这个类可以任意访问Coordinate中的数据
class Circle
{
public:
	void printXY()
	{
	  cout<<m_coor.m_iX<<m_coor.m_iY;
	}
private:
	Coordinate m_coor;
};

关于友元的注意事项:

  • 友元关系不可传递(A是B的朋友,B是C的朋友,A不一定是C的朋友)
  • 友元关系的单向性(A是B的友元,还是B是A的友元)
  • 友元声明的形式及数量不受限制
  • 友元只是封装的补充,是不得已而为之的做法

关键字:static

  • 静态数据成员:并不依赖于对象,而是依赖于类,不实例化对象,作为静态的数据成员仍然在内存当中存在。
  • 静态的成员函数:在静态的成员函数中无法调用非静态的数据成员或者是成员函数。
  • 注意事项:
  1. 静态数据成员必须单独初始化
  2. 静态成员函数不能调用非静态成员函数和非静态数据成员
  3. 静态数据成员只有一份,且不依赖对象而存在(例如,用sizeof()函数去判断一个对象的大小,结果不包括该类的数据成员)
  4. const和static不能连在一起用
//例子
class Tank
{
public:
	Tank() {s_iCount++;}
	~Tank() {s_iCount--;}
	static int getCount() {return s_iCount;}
	static int s_iCount;
private:
	string m_strCode;
};
int Tank::s_iCount = 0;
//访问方法有两种,不通过对象直接通过类来访问,或者是通过对象来访问
int main(void)
{
	cout<<Tank::s_iCount<<endl;
	cout<<Tank::getCount()<<endl;
	Tank tank;
	cout<<tank.getCount()<<endl;
	cout<<tank.s_iCount<<endl;
	return 0;
}

运算符重载

概念:给原有的运算符赋予新的功能
例如:使用+号来做运算符的拼接
本质:函数重载
关键字:operator

一元运算符重载
  • -(负号)的重载
  1. 通过友元函数重载:
//友元函数的重载
class Coordinate
{
friend Coordinate& operator-(Coordinate &coor);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//实现时
Coordinate& operator-(Coordinate &coor)
{
	coor.m_iX=-coor.m_iX;
	coor.m_iY=-coor.m_iY;
	return *this;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	-coor1; //operator-(coor1);
	return 0;
}
  1. 成员函数重载:
//成员函数的重载
class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate& operator-();
private:
	int m_iX;
	int m_iY;
};
//实现时
Coordinate& Coordinate::operator-()
{
	m_iX=-m_iX;
	m_iY=-m_iY;
	return *this;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	-coor1; //coor1.operator-();
	return 0;
}
  • ++符号的重载
  1. 前置++符号重载
class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate& operator++(); //前置++
private:
	int m_iX;
	int m_iY;
};
//实现时
Coordinate& Coordinate::operator++()
{
	m_iX++;
	m_iY++;
	return *this;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	++coor1; //coor1.operator++();
	return 0;
}
  1. 后置++符号重载
class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate operator++(int); //后置++
private:
	int m_iX;
	int m_iY;
};
//实现时
Coordinate Coordinate::operator++(int)
{
	Coordinate old(*this);
	m_iX++;
	m_iY++;
	return old;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	coor1++; //coor1.operator++(0);
	return 0;
	
}
二元运算符重载
  • +号运算符
  1. 友元函数重载
class Coordinate
{
friend Coordinate operator+(const Coordinate &c1,const Coordinate &c2);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//实现时
Coordinate operator+(const Coordinate &c1,const Coordinate &c2)
{
	Coordinate temp;
	temp.m_iX=c1.m_iX+c2.m_iX;
	temp.m_iY=c1.m_iY+c2.m_iY;
	return temp;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	Coordinate coor2(4,7);
	Coordinate coor3(0,0);
	coor3 = coor1+coor2; //operator+(coor1,coor2)
	return 0;
}
  1. 成员函数重载
class Coordinate
{
public:
	Coordinate(int x,int y);
	Coordinate operator+(const Coordinate &coor);
private:
	int m_iX;
	int m_iY; 
};
//实现时
Coordinate Coordinate::operator+(const Coordinate &coor)
{
	Coordinate temp(0,0);
	temp.m_iX = this->m_iX + coor.m_iX;
	temp.m_iY = this->m_iY + coor.m_iY;
	return temp;
}
//使用时
int main(void)
{
	Coordinate coor1(3,5);
	Coordinate coor2(4,7);
	Coordinate coor3(0,0);
	coor3=coor1+coor2; //coor1.operator+(coor2)
	return 0;
}
  • <<输出运算符重载:
    不可以通过成员函数重载,只可以通过友元函数重载
class Coordinate
{
friend ostream& operator<<(ostream &out,const Coordinate &coor);
public:
	Coordinate(int x,int y);
private:
	int m_iX;
	int m_iY;
};
//实现该函数时
ostream& operator<<(ostream &out,const Coordinate &coor)
{
	out << coor.m_iX<<","<<coor.m_iY;
	return out;	
}
//使用时
int main(void)
{
	Coordinate coor(3,5);
	cout<<coor;//operator<<(cout,coor);
	return 0;
}
  • [ ]索引运算符的重载:
    不能采用友元函数重载,只能使用成员函数重载
class Coordinate
{
public:
	Coordinate(int x,int y);
	int operator[](int index);
private:
	int m_iX;
	int m_iY;
};
//实现该函数时
int Coordinate::operator[](int index)
{
	if(0==index)
	{return m_iX;}
	if(1==index)
	{return m_iY};
}
//使用时
int main(void)
{
	Coordinate coor(3,5);
	cout<<coor[0]; //coor.operator[](0);
	cout<<coor[1]; //coor.operator[](1);
	return 0;
}

模板函数与模板类

函数模板
  • 使用模板的原因:
//函数1
int max(int a,int b){return (a>b)?a:b;}
//函数2
float max(float a,float b){return (a>b)?a:b;}
//函数3
char max(char a,char b){return (a>b)?a:b;}
  1. 最好有一种方案,把类型作为参数传进去,而通过计算机把这三个函数做出来
    关键字template typename class
template<class T>
T max(T a,T b)  //函数模板
{
	return (a>b)?a:b;
}

//使用时
int ival=max(100,99);  //模板函数
//通过typename定义函数模板
template<typename T>
void swap(T& a,T& b)
{
	T tmp = a;
	a=b;
	b=tmp;
}
  1. 变量作为模板的参数
template <int size>
void display()
{
	cout << size<<endl;
}
//使用时
display<10>();
  1. 多参数函数模板
template <typename T,typename C>
void display(T a,C b)
{
	cout<<a<<" "<<b<<endl;
}

typename和class可以混用
函数模板与重载:通过函数模板,可以得到不同的模板函数,这些模板函数之间就形成了重载

类模板
//先举个例子
template<class T>
class MyArray
{
public:
	void display()
	{......}
private:
	T *m_pArr;
};
//等到定义这个成员函数的时候
template<class T>
void MyArray<T>::display()
{
	......
}
//使用时
int main(void)
{
	MyArray<int> arr;
	arr.display();
	
	return 0;
}

模板代码不能分离编译,必须全部放在同一个.h文件中

标准模板库(STL: Standard Template Lib)

vector向量

本质:对数组的封装
特点:读取能在常数时间完成

//初始化vector对象的方式
//vector保存类型为T的对象。默认构造函数v1为空
vector<T> v1;
//v2是v1的一个副本
vector<T> v2(v1);
//v3包含n个值为i的元素
vector<T> v3(n,i);
//v4包含有值初始化元素的n个副本
vector<T> v4(n);

迭代器:

int main(void)
{
	vector vec;
	vec.push_back("hello");
	vector<string>::iterator citer = vec.begin();
	for(;citer!=vec.end();citer++)
	{cout<<*citer<<endl;}
	return 0;
}
链表List

特点:数据插入速度快

map:映射

键值对

猜你喜欢

转载自blog.csdn.net/qq_43348528/article/details/103576169