c++第十二天(友元和运算符重载)

22 篇文章 2 订阅

目录

友元

一、友元函数(类与整个程序之间)

二、友元类

三、类中的成员函数作友元 (类与类之间)

四、运算符重载的概念

五、重载运算符种类

六、运算符重载例子


友元

作用: 提高函数或者类的访问权限。 但是也会破坏封装性。所以不要随便使用友元。

 

一、友元函数(类与整个程序之间)

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;
}

要熟练掌握。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值