友元
1.友元的概念
C++提供了一种机制(语法规则):让其它的函数或者其它的类可以使用本类中定义的私有成员2.友元函数
定义:在普通函数的前面加上firend关键字,该函数就变成了友元函数
语法规则: friend 函数的返回值 函数名称(形参); //声明友元函数
3.友元类
语法规则:friend class 类名; //声明友元类
注意:友元函数的定义可以写在类的里面或者类的外面
#include <iostream>
using namespace std;
//定义银行账户类
class Bankcount
{
public:
Bankcount(string _name,double _money)
{
name=_name;
money=_money;
}
//声明show函数是Bankcount类的友元函数
friend void show(Bankcount &other)
{
cout<<"户主是: "<<other.name<<endl;
cout<<"余额是: "<<other.money<<endl;
}
private:
double money; //余额
string name; //账户名字
};
int main()
{
Bankcount b("马云",1000000000000000.0);
show(b);
}
#include <iostream>
using namespace std;
//定义银行账户类
class Bankcount
{
public:
Bankcount(string _name,double _money)
{
name=_name;
money=_money;
}
//声明show函数是Bankcount类的友元函数
friend void show(Bankcount &other);
private:
double money; //余额
string name; //账户名字
};
//友元函数的定义写在类的外面
void show(Bankcount &other)
{
cout<<"户主是: "<<other.name<<endl;
cout<<"余额是: "<<other.money<<endl;
}
int main()
{
Bankcount b("马云",1000000000000000.0);
show(b);
}
友元类,以及互为友元类
#include <iostream>
using namespace std;
class Person; //前向引用声明(告诉编译器,我有定义Person类,只是说在后面定义,我先跟编译器打声招呼)
//定义银行账户类
class Bankcount
{
public:
Bankcount(string _name,double _money)
{
name=_name;
money=_money;
}
//声明Person类是我的友元类
friend class Person;
private:
double money; //余额
string name; //账户名字
};
//定义Person类--》跟银行账户类没有关系
class Person
{
public:
Person(string _name)
{
name=_name;
}
//我想查看某个人的银行账户信息
void show(Bankcount &other)
{
cout<<"账户是: "<<other.name<<endl;
cout<<"余额是: "<<other.money<<endl;
}
private:
string name;
};
int main()
{
Bankcount b("马云",1000000000000000.0);
Person p("老师");
p.show(b);
}
#include <iostream>
using namespace std;
class A; //前向引用:只是告诉编译器后面有定义A这个类,但是这个类中具体有什么成员还是不知道
class B
{
public:
void show(A _new);
//声明了A是B的友元类
friend class A;
private:
int c;
double d;
};
class A
{
public:
void show(B _new)
{
cout << "c: " << _new.c << endl;
cout << "d: " << _new.d << endl;
}
//声明了B是A的友元类
friend class B;
private:
int a;
double b;
};
void B::show(A _new)
{
cout << "a: " << _new.a << endl;
cout << "b: " << _new.b << endl;
}
int main()
{
A aa;
B bb;
aa.show(bb);
bb.show(aa);
}
模板(参数和返回值抽象为模板)--》泛型编程
模板是C++中引入的一种泛型编程技术
泛型:通用类型
1.引入模板
函数重载非常的啰嗦,需要动手写N个版本的add
int add(int a,int b)
double add(double a,double b)
C++的设计者想了一个优化的办法,上面两个版本的add仅仅只是参数类型不同而已,我为何不可以把参数类型抽象出来,用一种特殊符号表示形参和返回值的类型
抽象为:
T add(T a,T b); //伟大的设想,到时候用户传递的实参是什么类型,那么T就是什么类型2.语法规则
template //C++中的关键字
typename //C++中的关键字
template<typename T> //声明一个模板,给这个模板取名叫做T
或者template<class T> //声明一个模板,给这个模板取名叫做T
T add(T a,T b) //模板函数
{
函数的源码
}
注意:模板不能共用(每个模板函数都要单独声明自己的模板),前面声明的模板,后面的函数如果还需要使用模板(要单独声明)3.模板函数
定义:只要一个函数中使用了模板,该函数就是模板函数
底层原理(模板的实例化):C++的编译器会依据函数调用时候传递的实参类型,去替换掉模板T的类型
模板函数跟具体版本的函数放在一起,优先调用具体版本的函数4..模板类
定义:只要一个类中使用了模板,这个类就是模板类
创建对象:
类名<模板的类型> 对象名;
比如: Cat<int> c1;
using namespace std;
//定义一个模板函数
template<typename T> //声明一个模板,叫做T
T add(T a,T b) //表示a,b以及函数返回值类型必须是相同的
{
cout<<"模板函数被调用了"<<endl;
return a+b;
}
int main()
{
int a=99;
int b=77;
double c=87.5;
double d=78.3;
//调用模板函数
cout<<"a+b is: "<<add(a,b)<<endl; //模板的实例化,理解为 add(int,int)
cout<<"c+d is: "<<add(c,d)<<endl; //模板的实例化,理解为 add(double,double)
//error: no matching function for call to ‘add(int&, double&)’
cout<<"a+c is: "<<add(a,c)<<endl; //模板的实例化,理解为 add(int,double)
}
#include <iostream>
using namespace std;
//定义一个模板函数
template<typename T1,typename T2> //声明两个模板,叫做T1和T2
T2 add(T1 a,T2 b)
{
cout<<"模板函数被调用了"<<endl;
return a+b;
}
int main()
{
int a=99;
int b=77;
double c=87.5;
double d=78.3;
//调用模板函数
cout<<"a+b is: "<<add(a,b)<<endl; //模板的实例化,理解为 add(int,int)
cout<<"c+d is: "<<add(c,d)<<endl; //模板的实例化,理解为 add(double,double)
cout<<"a+c is: "<<add(a,c)<<endl; //模板的实例化,理解为 add(int,double)
}
#include <iostream>
using namespace std;
template<typename T>
T add(T a,T b) //模板函数
{
cout<<"版本1"<<endl;
}
template<typename T>
T add(T a,int b) //部分模板,部分具体
{
cout<<"版本2"<<endl;
}
int add(int a,int b) //具体版本的add
{
cout<<"版本3"<<endl;
}
int main()
{
int a=99;
int b=77;
char c='@';
double d=78.5;
add(d,b);
}
#include <iostream>
using namespace std;
template<typename T>
class myarray
{
public:
//构造函数初始化
myarray(int _n)
{
n=_n;
buf=new T[n];
}
//析构释放
~myarray()
{
delete []buf;
}
//遍历数组
void show()
{
int i;
for(i=0; i<n; i++)
cout<<"buf成员是: "<<buf[i]<<endl;
}
//存放数据到数组
void putdata(T data,int i)
{
buf[i]=data;
}
//返回数组下标为i的成员
T at(int i)
{
return buf[i];
}
private:
T *buf;
int n;
};
int main()
{
//int类型
// myarray<int> array1(3);
// array1.putdata(5,0);
// array1.putdata(6,1);
// array1.putdata(7,2);
// array1.show();
// cout<<"下标1的数据是: "<<array1.at(1)<<endl;
//string类型
myarray<string> array1(3);
array1.putdata("hello",0);
array1.putdata("gec",1);
array1.putdata("中国人",2);
array1.show();
cout<<"下标1的数据是: "<<array1.at(1)<<endl;
}
#include <iostream>
using namespace std;
//定义一个模板类
template<typename T>
class Cat
{
public:
Cat(T _n)
{
n=_n;
}
void show() const
{
cout<<"n is:"<<n<<endl;
}
private:
T n;
int age;
};
int main()
{
//创建一个猫的对象
//错误的,模板类创建对象必须传递模板参数
//Cat c1(5);
//正确写法
Cat<int> c1(5);
c1.show();
Cat<double> c2(8.5);
c2.show();
Cat<string> c3("gec");
c3.show();
}
#include <iostream>
using namespace std;
//定义两个模板类
template<typename T1,typename T2>
class Cat
{
public:
Cat(T1 _n,T2 _m)
{
n=_n;
m=_m;
}
void show() const
{
cout<<"n is:"<<n<<endl;
cout<<"m is:"<<m<<endl;
}
private:
T1 n;
T2 m;
};
int main()
{
//创建一个猫的对象
Cat<int,double> c1(5,7.5);
c1.show();
Cat<int,int> c2(10,8);
c2.show();
}