友元
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,此时就要用到友元。
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的三种实现
- 全局函数做友元
将函数的声明写进类中(不用写在public或private中),并在声明前加friend关键词即可。
class Building
{
//告诉编译器 goodGay全局函数 是 Building类的好朋友,可以访问类中的私有内容
friend void goodGay(Building * building);
public:
private: int a;
};
void goodGay(Building * building) //全局函数
{
}
- 类做友元
同上,将友元类的声明放在目标类中,并在声明前加friend关键词即可。
- 成员函数做友元
同上,需要注意的是要声明友元成员函数是属于哪个类的。
运算符重载
运算符重载:通过用全局函数或成员函数给运算符定义一个新的运算方式。
加号运算符重载:
左移运算符重载:
//定义左移运算符重载,让“cout << 对象”时输出该对象的成员变量a和b
#include<iostream>
//通常不会利用成员函数重载左移运算符,因为无法实现std::cout在左侧
class person
{
friend std::ostream &operator<<(std::ostream &cout,person &p);
public:
person(int x,int y) //创建构造函数让用户初始化成员变量
{
a = x;
b = y;
}
private:
int a,b;
};
std::ostream &operator<<(std::ostream &cout,person &p) //利用全局函数实现左移运算符的重载
{ /*cout的数据类型是ostream(标准的输出流对象),
且该对象全局只能有一个不能创建
一个新的cout,故要用引用的方式返回
用到(链式编程思想)。*/
std::cout << "p.a=" << p.a << " p.b=" << p.b ;
return cout; //返回cout,可无限的在其后面追加,如追加 << std::endl;
}
void test1()
{
person p(10,10); //给对象p的成员变量初始化值
std::cout << p << std::endl; //若不返回cout,则p后面不能在跟左移运算符以及其他东西
}
int main(){
test1(); //调用test1函数
return 0;
}
前置后置递增运算符重载:
//要求:自己定义一个像int一样的数据类型(可自增)
#include<iostream>
class MyInteger
{
friend std::ostream &operator<<(std::ostream &cout,MyInteger &myint);
public:
MyInteger &operator++() //前置递增重载,前置递增:前自增,在运算
{ //函数返回值为引用的原因是为了一直对一个数据进行递增操作
//若不返回引用则是创建了一个与a值相同的新对象
a++;
return *this; //返回自身
}
MyInteger operator++(int) //后置递增先输出(返回)结果,再进行运算
{ //注意:前置返回引用,后置返回值,因为后置返回的是在成员函数中创建的临时变量在栈区,会被释放
MyInteger temp;
temp = *this; //创建一个临时对象,记录此时的值,然后返回这个临时值
a++; //实现后置递增+1的功能
return temp; //注意:由于返回的是temp的值,故此处的后置递增无法实现链式思想!
}
MyInteger()
{
a = 0; //令定义的该数据类型初始值为0;
}
private:
int a;
};
//左移运算符重载:实现cout << “对象” 显示该对象的成员变量的功能。
std::ostream &operator<<(std::ostream &cout,MyInteger &myint) //返回值类型加引用是为了返回cout本身
//因为全局只有一个cout,不能创建
{
cout << myint.a;
return cout;
}
void test1()
{
MyInteger myint; //创建一个对象
std::cout << myint++ << std::endl; //输出结果:0
std::cout << myint << std::endl; //输出结果:1
}
int main()
{
test1();
return 0;
}