友元
为什么需要:在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
目的:让一个函数或者类访问另一个类中私有的成员
友元的关键字:friend
友元的三种实现
1.全局函数做友元
2.类做友元
3.成员函数做友元
运算符重载:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
编译器给运算符起了一个通用的名称operator运算符
加号运算符重载
作用:实现两个自定义数据类型相加的运算
//1.成员函数重载+号
Person operator+(Person &p)
{
Person temp;
temp.m_a=this->m_a+p.m_a;
temp.m_b=this->m_b+p.m_b;
return temp;
}(m_a,m_b已经在Person类中定义了)
这样就能用自定义的类型做加法了 例如:Person p3=p1+p2;(p1+p2就调用了上面那个函数)
//成员函数重载本质调用:Person p3=p1.operator+(p2);
//2.全局函数重载+号
Person operator+(Person &p1, Person &p2)
{
Person temp;
temp.m_a=p1.m_a+p2.m_a;
temp.m_b=p1.m_b+p2.m_b;
return temp;
}
//全局函数重载本质调用
Person p3=operator+(p1,p2);
总结:1.成员函数重载和全局函数重载就少了个引用
2.运算符重载也可以发生函数重载
3.对于内置的数据类型的表达式的运算符时不可能改变的
4.不要滥用运算符重载
左移运算符重载
作用:可以输出自定义数据类型
//利用成员函数重载 左移运算符 p.operator<<(cout) 简化版本p<<cout
//不会利用成员函数重载<<运算符,因为无法实现cout在左侧
//只能用全局函数重载左移运算符
ostream & operator<<(ostream &cout , Person &p)//本质 operator<<(cout ,p )
{
cout <<p.m_a<<p.m_b;
return cout;
}
//因为ostream下只有cout这一个对象所以要用cout做参数只能用引用
//因为返回值时cout所以函数的类型是返回值的类型ostream
//因为要一直返回一个cout所以ostream 后面还要加& 才会返回一个cout
递增运算符重载
作用:通过重载递增运算符,实现自己的整型数据
//重载前置++运算符
mynum& operator++()
{
//先++
num++;
return *this;
}(mynum是类,num是mynum类下的成员)
//如果只是返回一次可以不用引用,但是要返回多次要用引用否则返回的是num'不是num
//后置递增++运算符
mynum operator++(int)//填int是为了函数重载,可以用于区分前置和后置递增
{
先 记录当时的值
mynum temp =*this;
再加1
num++;
return temp;
}
//因为后置递增要先计算表达式的值再进行自增所以要一个变量来记录原来的值
//不返回引用而返回值的原因是因为返回的是局部的变量当函数调用完之后就被释放了所以要返回值
//重载 赋值运算符
Person& operator=(Person &p)//简化版本 p2=p1
{
//编译器提供的是浅拷贝
//Age=p.age;(就是单纯把数据复制然后粘贴到另一个变量上去)
//应该判断四回复有属性再堆区,如果有先释放干净,然后再深拷贝
if(Age!=NULL)
{
delete Age;
Age =NULL;
Age = new int(*p.age);
return *this;
}
//Age是在Person里面创建的指针
关系运算符重载
作用:重载关系运算符,可以让两个自定义类型对象进行对比操作
bool operator==(Person &p)
{
if(this->name==p.name&&this->age==p.age)
{
return true;
}
return false;
}//返回布尔类型是因为这个函数是在if条件里面调用的所以用布尔来判断真假
函数调用运算符重载
1.函数调用运算符()也可以重载
2.由于重载后使用的方式非常想函数的调用,因此成为仿函数
3.仿函数没有固定写法,非常灵活
void test01()
{
print myprint;
myprint("hello world");//由于使用起来非常类似于函数调用,因此成为仿函数
}
void operator()(string test)
{
cout <<test<<end;
}//