6、C++中的友元与运算符重载

一、C++中的友元

1、C++中的访问权限

class base
{
    
    
	public: //共有成员,类内,子类,类外,都可以访问
		int a;
	protected: //保护成员,类内,子类可以访问
		int b;
	private: //私有成员,类内可以访问
		int c;
};

2、友元

  • 作用:用于访问类中的所有成员
  • 缺点:会破坏类的封装性,所以不要随便用友元

3、友元函数

语法:

friend 函数的返回值类型 函数名 (参数列表)
---------------------------------------
例子:
friend void show()//该函数就可以访问类中的所有成员
{
    
    
	
}
  • 1、当一个函数被声明为友元函数时,该函数就不属于类中的成员函数
  • 2、友元函数必须要在类内声明
  • 3、友元函数可以在类内任意位置声明,与成员权限无关

在这里插入图片描述
例子:

#include <iostream>
using namespace std;

class base
{
    
    
    public:
        int a;
    protected:
        int b;
    private:
        int c;
    
    friend void show();
};

//base类的友元函数
void show()
{
    
    
    base a;
    a.a = 100;
    a.b = 200;
    a.c = 300;

    cout << a.a << endl;
    cout << a.b << endl;
    cout << a.c << endl;
}

int main()
{
    
    
    show();
}

4、友元函数可以继承吗

class base
{
    
    
	private:
		int a;
	//声明一个 set 友元函数
	friend void set();
};

class new_base:public base
{
    
    
	private:
		int b;
	//声明一个 set 友元函数
	//friend void set();假设不重新声明友元函数就不能访问私有成员
};
void set()
{
    
    
	base a;
	a.a = 1000; //可以访问私有 成员
	cout << a.a << endl;
	new_base b;
	b.b = 2000; //不可以访问 new_base 的私有成员。
}
  • 1、友元函数是不可以继承的
  • 2、假设需要友元函数可以访问子类的私有成员,则需要在子类中再次声明该函数为友元函数
  • 3、多个类可以对应一个友元函数
  • 4、一个类可以对应多个友元函数

二、友元类

作用:

  • 当一个类为另一个类的友类时,则该类可以访问对方的所有数据成员

语法:

friend class 类名
----------------
例子:
friend class base;

在这里插入图片描述
练习: 让两个类互为友元。

#include <iostream>
using namespace std;

class base2;

class base1
{
    
    
    public:
        void set_b2();
        int a;
    protected:
        int b;
    private:
        int c;

    friend class base2;
};

class base2
{
    
    
    public:
        void set_b1()
        {
    
    
            base1 b1;
            b1.a = 10;
            b1.b = 20;
            b1.c = 30;
        }
        int a;
    protected:
        int b;
    private:
        int c;

    friend class base1;
};

//在base 定义后 才实现 set_base接口
void base1 :: set_b2()
{
    
    
    base2 b2;
    b2.a = 30;
    b2.b = 20;
    b2.c = 10;
}

int main()
{
    
    

}

三、运算符重载

1、作用:

  • 给已知的运算符赋予新的功能。比如:两个字符串的相加 , 两个类的相加,两个结构体的相加等。

语法:

返回类型 operator 运算符号 (参数列表)
------------------------------------
例子:重载两个类相加
base operator+(base a)
{
    
    
	
}

2、可重载运算符:

哪些运算能重载
双目运算符 (+,-,,/, %) operator+
关系运算符 (==, !=, <, >, <=, >=)
逻辑运算符 (||, &&, !)
单目运算符 (
, &, ++, --)
位运算符 (|, &, ~, ^, <<, >>)
赋值运算符 (=, +=, -=, …)
空间申请运算符 (new , delete)
其他运算符 ((), ->, [])

3、不可重载运算符:

哪些运算符不能重载
.(成员访问运算符)
.*(成员指针访问运算符)
::(域运算符)
sizeof(数据类型长度运算符)
?:(条件运算符, 三目运算符)

4、运算符重载的两种方式

类内重载方式:
	base operator+(参数列表)
调用规律:
	base c = a + b;  - > a.operator+(b)//两者等价
特点:
	a是调用者,b是参数。
	在类的内部重载,友this指针
类外重载方式:
	base operator+(base a, base b)
调用规律:
	base c = a + b;   ->    operator+(a, b)//两者等价
特点:
	a和b都是operator的参数,可以不用this指针

总结:

  • 这两种重载运算符的方式都是一样的,用户根据自己的需要选择

四、不同运算符重载的方式

1、关系运算符:

#include <iostream>
using namespace std;

class base 
{
    
    
    public:
        base(int a) : a(a){
    
    }

    private:
        int a;

    friend bool operator>(base a, base b);
};

//内外重载
bool operator>(base a, base b)
{
    
    
    if(a.a > b.a)
    {
    
    
        return true;
    }
    else
    {
    
    
        return false;
    }
}

int main()
{
    
    
    base b1(10);
    base b2(100);

    if(b1 > b2)
    {
    
    
        cout << "b1 > b2" << endl;
    }
    else
    {
    
    
        cout << "b1 < b2" << endl;
    }
}

2、逻辑运算符

#include <iostream>
using namespace std;


class base
{
    
    
    public:
        base(int a) : a(a){
    
    }

        bool operator&&(base a)
        {
    
    
            if(this->a && a.a)
            {
    
    
                return true;
            }
            else
            {
    
    
                return false;
            }
        }
    private:
        int a;
};

int main()
{
    
    
    base a(100);
    base b(10);

    if(a&&b)
    {
    
    
        cout << "true" << endl;
    }
    else
    {
    
    
        cout << "false" << endl;
    }
}

3、单目运算符

#include <iostream>
using namespace std;

class base
{
    
    
    public:
        int a;
    base(int a) : a(a){
    
    }
    //++a 先自加,再用值
    base operator++()
    {
    
    
        cout << "调用++a" << endl; 
        this->a++;
        return *this;
    }

    //a++ 先用值,再自加
    base operator++(int)
    {
    
    
        cout << "调用a++" << endl;
        base tmp=*this; //保存原来的值
        this->a++;
        return tmp; //先返回值
    }
};

int main()
{
    
    
    base a(10);
    base b = a++;
    cout << a.a << endl;
    cout << b.a << endl;
}

利用位运算符 << , >>实现输入输出的重载

1、输出运算符的重载

#include <iostream>
#include <ostream>

using namespace std;

class base
{
    
    
    public:
        base(int a) : a(a){
    
    }

    private:
        int a;
    
    friend ostream &operator<<(ostream &out, base a);
};

//内外重载
ostream &operator<<(ostream &out, base a)
{
    
    
    cout << a.a;

    return out;
}

int main()
{
    
    
    base a(10086);
    base b(10010);

    cout << a << b << endl;
}

2、输入运算符的重载

#include <iostream>
#include <istream>
using namespace std;


class base
{
    
    
    public:
        int a;
        base(){
    
    }
        base(int a) : a(a){
    
    }
};

istream & operator>>(istream &in,base &a)
{
    
    
    cin >> a.a;
    return in;
}

int main()
{
    
    
    base a;
    base b;

    cin >> a >> b;

    cout << a.a << endl;
    cout << b.a << endl;
}

五、字符串类的使用

在这里插入图片描述
所有的字符串操作都可以使用string类去处理

构造函数

// 默认构造函数,创建一个空字符串
string();

// 构造函数,以指定字符重复构造字符串
string(size_type length, char ch);

// 构造函数,以C风格字符串创建字符串
string(const char *str);

// 构造函数,从C风格字符串中指定位置和长度创建字符串
string(const char *str, size_type length);

// 构造函数,从另一个字符串截取子串
string(string &str, size_type index, size_type length);

string 重载后的运算符:

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_53402930/article/details/132459089