目录
友元
作用: 提高函数或者类的访问权限。 但是也会破坏封装性。所以不要随便使用友元。
一、友元函数(类与整个程序之间)
1、语法: class 类名{
friend 返回值类型 函数名(参数列表);
};
例子: friend void init_f(); //声明友元格式:friend 返回类型 函数名(参数);
friend void show_f(); //友元只能在类内定义 ,在类外赋值初始化。
2、注意:
(1)友函数的声明必须要在类内。 error: ‘friend’ used outside of class 。
(2)友函数不是类中的成员函数。
3、友元传参
//声明友元格式:friend 返回类型 函数名(参数);
friend void init_f ( Father &F, int a, int b, int c ) ;
//友元只能在类内定义
friend void show_f ( Father &F ) ;
4、注意:友元是无法继承的。
(1)问:一个类可以有多个友元函数吗?
答:肯定可以!
(2)问:一个友元函数可以对应多个类吗?
答:肯定可以!
二、友元类
作用:使一个类里面的所有成员函数,可以访问另外一个类的一切数据成员!
1、语法: class 类名{
friend class 另外的类名; //声明另外一个类是当前的友元类
}
2、例子:
先声明,防止编译器找不到类报错
class xh;
class xm;
小明类
class xm{
friend class xh; 将小花变成我的好朋友,可以访问我所有数据,友元类.
private:
int age;
public:
void show_xh();
};
小花类
class xh{
friend class xm; 将小明变成我的好朋友,可以访问我所有数据,友元类.
private:
int id;
public:
void show_xm();
};
3、类外初始化:
用小花里面的函数访问小明的私有成员
void xh::show_xm(){
xm m;
m.age = 10; //访问小明的私有成员
cout << m.age << endl;
}
用小明里面的函数访问小花的私有成员
void xm::show_xh(){
xh h1;
h1.id = 20;
cout << h1.id << endl;
}
三、类中的成员函数作友元 (类与类之间)
作用:使一个类里面的某一个函数,是另外一个类的友元函数 。
class base {
public:
base(int date) : date(date) { }
private:
int date;
friend void xbase::show_base(base &tmp); //只声明 xbase::show_base 是当前base 的友元
};
四、运算符重载的概念
作用: 重新定义运算符的操作函数。增强运算符的功能。关键字:operator
1、为什么需要运算符重载??
答:因为无法对用户自定义的数据类型进行计算,比如:类与类的加法。
2、所以遇到无法直接操作的数据类型,我们就需要使用运算符重载,赋予运算符新的功能。
语法:
返回类型 operator 运算符符号( <参数表> ) {
函数体
}
五、重载运算符种类
1、那些运算能重载
双目运算符 (+,-,*,/, %)
关系运算符 (==, !=, <, >, <=, >=)
逻辑运算符 (||, &&, !)
单目运算符 (*, &, ++, --)
位运算符 (|, &, ~, ^, <<, >>)
赋值运算符 (=, +=, -=, .....)
空间申请运算符 (new , delete)
其他运算符 ((), ->, [])
2、哪些运算符不能重载
.(成员访问运算符)
.*(成员指针访问运算符)
::(域运算符)
sizeof(数据类型长度运算符)
?:(条件运算符, 三目运算符)
六、运算符重载例子
1、operator+ , operator%(双目运算符)
//重写下述类的 + 法 和 % 号运算符
#include<iostream>
using namespace std;
class test{
private:
int a;
float b;
public:
test(){}
test(int a,float b):a(a),b(b){ }
//设置访问私有成员接口。
void show(){
this->a = a;
this->b = b;
cout << a+b << endl;
}
friend test operator + (test a,test b);
friend int operator%(test i,int d);
};
重载+号运算符
test operator + (test a,test b){
test sum ;
sum.a = a.a + b.a;
sum.b = a.b + b.b;
return sum;
}
重载%号运算符
int operator%(test i,int d){
int sum = i.a + (int)i.b;
return sum%d;
}
int main()
{
test t1(17,10);
test t2(10,3.33);
test sum = t1 + t2; 返回两个类相加的对象。
sum.show(); 调用函数显示相加后的结果。
int data = t1%4; 重载%运算符,使t1能够取余10。
cout << data << endl;
返回类型为int型,运算过程在operator函数里面完成。只要外部取余重载后返回的值。
}
2、operator<,operator>,operator==(关系运算符)
#include<iostream>
using namespace std;
class base{
private:
int data;
public:
base(int a):data(a){}
friend bool operator==(base a,base b);
friend bool operator< (base a,base b);
friend bool operator> (base a,base b);
};
重载==关系运算符。
bool operator==(base a,base b){
if(a.data==b.data){
return true;
}else{
return false;
}
}
重载<关系运算符
bool operator< (base a,base b){
if(a.data<b.data){
return true;
}else{
return false;
}
}
重载>关系运算符。
bool operator> (base a,base b){
if(a.data>b.data){
return true;
}else{
return false;
}
}
int main()
{
base a(11);
base b(11);
类与类进行比较,实现运算符重载意义。
重载==运算符。
if(a==b){
cout << "a=b" << endl;
}
重载 >和< 运算符。
else if(a>b){
cout << "a>b" << endl;
}
else if(a<b){
cout << "a<b" << endl;
}
}
3、operator&&,operator||(逻辑运算符)
#include<iostream>
using namespace std;
class base{
public:
int data;
base(int a):data(a){}
friend bool operator&&(base a,base b);
friend bool operator||(base a,base b);
};
重载&&关系运算符。
bool operator&&(base a,base b){
if(a.data&&b.data){
return true;
}else{
return false;
}
}
重载||关系运算符。
bool operator||(base a,base b){
if(a.data||b.data){
return true;
}else{
return false;
}
}
int main()
{
逻辑运算符&&的重载,0为假,其他为真。
base a(1);
base b(0);
if(a&&b){
cout << "a&&b为真" << endl;
}else{
cout << "a&&b为假" << endl;
}
逻辑运算符||的重载,两个为0为则为假,其他为真。
if(a||b){
cout << "a||b为真" << endl;
}else{
cout << "a||b为假" << endl;
}
}
4、operator++,operator--(单目运算符)
#include<iostream>
using namespace std;
class base{
public:
int data;
base(int a):data(a){}
};
重载a++关系运算符
base operator++(base &a,int){
return a.data++; //发生隐式转换,变成base类型
}
重载++a运算符
base operator++(base &a){
a.data++;
return a;
}
重载a--运算符
base operator--(base &a,int){
return a.data--;
}
重载--a运算符
base operator--(base &a){
a.data--;
return a;
}
int main()
{
base a(10);
重载a++运算符
cout << "a=" << a.data << endl;
base c = a++; 赋值给构造函数的参数,给到数据成员。
cout << "a++后:" << endl;
cout << a.data << endl; //应该返回11
cout << c.data << endl; //应该返回10,先赋值给c后a再加1.
重载++a运算符
base d = ++a; 直接返回赋值结果
cout << "++a后:" << endl;
cout << a.data << endl; //应该返回12
cout << d.data << endl; //应该返回12
重载a--运算符
base b = a--;
cout << "a--后:" << endl;
cout << a.data << endl; //应该返回11
cout << b.data << endl; //应该返回12
重载--a运算符
base e = --a;
cout << "--a后:" << endl;
cout << a.data << endl; //应该返回10
cout << e.data << endl; //应该返回10
}
5、operator&,operator|(按位运算符)
#include<iostream>
using namespace std;
class base{
public:
int data;
base(int a):data(a){}
};
按位或运算
base operator|(base a,base b){
return a.data|b.data;
}
按位与运算
base operator&(base a,base b){
return a.data&b.data;
}
int main()
{
base a(0x7); //0111
base b(0x3); //0011
按位或运算
base c = a|b;
cout << c.data << endl;
按位与运算
base d = a&b;
cout << d.data << endl;
}
6、operator<<,operator>>
#include<iostream>
#include<string.h>
using namespace std;
class Person{
private:
int age;
char name[10];
public:
Person(){}
Person(int age,const char *name):age(age){
strcpy(this->name,name);
}
friend istream & operator>>(istream &i,Person &a);
friend ostream & operator<<(ostream &o,Person &a);
};
重载输出流<<运算符
ostream & operator<<(ostream &o,Person &a){ c++规定的写法,按照这样写返回类型和参数
cout << a.age << "岁 ";
cout << a.name;
return o; //不返回也行
}
重载输入流>>运算符
istream & operator>>(istream &i,Person &a){ c++规定的写法,按照这样写返回类型和参数
cin >> a.age;
cin >> a.name;
return i; //不返回也行
}
int main()
{
Person a(10,"小爱");
Person b(12,"小妹");
Person c(14,"小可");
cout << "年龄:姓名\n";
cout << a << endl << b<< endl << c << endl;
cout << "请输入:三个年龄和姓名\n";
cin >> a >> b >> c;
cout << "年龄:姓名\n";
cout << a << endl << b<< endl << c<< endl;
}
7、operator=
#include <iostream>
using namespace std;
赋值运算符= 的重载只能写到类内,而且要是隐式转换不了的时候使用才行。
class base
{
public:
base() {}
base(int d, int d1) : data(d), data1(d1) { cout << "带参构造" << endl; }
base(base &tmp) { cout << "重写拷贝" << endl; }
类中的成员函数
base operator=(int tmp)
{
cout << "调用赋值运算符" << endl;
this->data1 = tmp;
this->data = tmp;
}
private:
int data;
int data1;
};
class tt
{
};
在对象赋值过程中有隐式转换,就会使用隐式,没有就会使用赋值运算符。
int main()
{
// base tmp=10; 这里调用了赋值运算符吗?不是,使用了隐式转换 base tmp(10);
base a;
a = 20; 这是调用了赋值运算符。
tt tmp; 定义另一个类。
base b = tmp; 拷贝构造,两个不同的类。
b = tmp; 调用了赋值运算符。
}
8、类内重载
#include<iostream>
using namespace std;
class base{
private:
int data;
public:
base(){}
base(int d):data(d){ }
base operator+(base tmp){
cout << this->data << endl;
cout << tmp.data << endl;
base t;
t.data = this->data = tmp.data;
return t;
}
};
int main()
{
base a(10);
base b(20);
base c=a+b;
}
要熟练掌握。