C++中运算符重载、匿名对象、友元的介绍,以及常成员函数和常对象

特殊成员函数

拷贝赋值函数

功能

用一个对象给另一个对象赋值

格式

函数名:operator=
返回值:自身的引用
函数的参数:同类的类对象引用

类名 & operator=(const 类名& other)
{
    
}

练习
封装学生的类,写出构造函数,析构函数、构造拷贝函数、拷贝赋值函数

#include <iostream>

using namespace std;
//定义一个学生类,成员属性为姓名和年龄
class Stu
{
    string name;
    int age;
public:
    //无参构造函数
    Stu()
    {
        cout << "Stu的无参构造" << endl;
    }
    //有参构造函数
    Stu(string name,int age):name(name),age(age)
    {
        cout << "Stu的有参构造" << endl;
    }
    //拷贝构造函数
    Stu(const Stu &other):name(other.name),age(other.age)
    {
        cout << "Stu的拷贝构造函数" << endl;
    }
    //拷贝赋值函数
    Stu & operator = (const Stu &other)
    {
        name = other.name;
        age = other.age;
        cout << "Stu的拷贝赋值函数" << endl;
        return *this;
    }
    //析构函数
    ~Stu()
    {
        cout << "Stu的析构函数" << endl;
    }
};

int main()
{
    Stu s1;
    cout << "----------------------------" << endl;
    Stu s2("zhangsan",14);
    cout << "----------------------------" << endl;
    Stu s3 = s2;
    cout << "----------------------------" << endl;
    Stu s4;
    s4 = s2;
    cout << "----------------------------" << endl;
    return 0;
}

匿名对象

匿名对象就是没有名字的对象

用处

  • 用匿名对象给有名对象初始化
  • 用匿名对象给对象数组初始化
  • 用匿名对象做函数实参

格式

类名();

示例代码

#include <iostream>

using namespace std;

class Stu
{
private:
    string name;
    int age;
public:
    //无参构造
    Stu() {}

    //有参构造
    Stu(string name,int age):name(name),age(age)
    {}
    void show()
    {
        cout << name << endl;
        cout << age << endl;
    }
};
void fun(Stu s)  //Stu s = Stu("lisi",23)
{
    s.show();
}
int main()
{
    Stu s1 = Stu("zhangsan",34);  //用匿名对象给有名对象初始化
    s1.show();

    Stu s[3] = {Stu("a",2),Stu("b",4),Stu("c",4)};

    fun(Stu("lisi",23)); //匿名对象做函数的实参
    return 0;
}

友元

作用

友元,让一个函数或者类,访问另一个类的私有数据成员

种类

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元

全局函数做友元

#include <iostream>

using namespace std;
//封装 房间 类
class Room
{
    friend void goodGay(Room &r);//goodGay函数是本类的好朋友,可以访问本类的所有成员
 
private:
    string m_BedRoom;  //卧室
public:
    string m_SittingRoom; //客厅
public:
    //无参
    Room()
    {
        m_BedRoom = "卧室";
        m_SittingRoom = "客厅";
    }
};

//全局函数做友元
void goodGay(Room &r)
{
    cout << "好朋友函数正在访问。。"  << r.m_SittingRoom << endl;
    cout << "好朋友函数正在访问。。"  << r.m_BedRoom << endl;
}
int main()
{
    Room r;
    goodGay(r);

    return 0;
}

类做友元

#include <iostream>

using namespace std;

//封装 房间 类
class Room
{

    friend class GoodGay;  //GoodGay这个类是本类的好朋友。可以访问本类的所有成员
private:
    string m_BedRoom;  //卧室
public:
    string m_SittingRoom; //客厅
public:
    //无参
    Room()
    {
        m_BedRoom = "卧室";
        m_SittingRoom = "客厅";
    }
};

//类做友元
class GoodGay
{
public:
    Room *r;
    void visit()
    {
        cout << "好基友类正在访问。。" << r->m_SittingRoom << endl;
        cout << "好基友类正在访问。。"  << r->m_BedRoom << endl;
    }
    GoodGay()
    {
        r = new Room;
    }
};
int main()
{
    GoodGay g;
    g.visit();
    return 0;
}

成员函数做友元

#include <iostream>

using namespace std;

class Room;//声明有这样的类

//类做友元
class GoodGay
{
public:
    Room *r;
    void visit();//在类内声明
    GoodGay();
};
//封装 房间 类
class Room
{
    friend void GoodGay::visit();  //这个类的成员函数是本类的好朋友。可以访问本类所有成员
private:
    string m_BedRoom;  //卧室
public:
    string m_SittingRoom; //客厅
public:
    //无参
    Room()
    {
        m_BedRoom = "卧室";
        m_SittingRoom = "客厅";
    }
};


void GoodGay::visit()  //在类外定义成员函数
{
     cout << "好朋友类正在访问。。" << r->m_SittingRoom << endl;
     cout << "好朋友类正在访问。。"  << r->m_BedRoom << endl;
}
GoodGay::GoodGay()
{
    r = new Room;
}
int main()
{
    GoodGay g;
    g.visit();
    return 0;
}

注意事项

  • 不要过度使用友元,会降低封装性
  • 友元不具有交换性、传递性、继承性

常成员函数和常对象

const的一些常见用法

const int a = 10;  //a不能被改变
int const *p;  //指针的指向可变,指向里的值不可变
int * const p; // 指针的指向不可变,指向里的值可变
int const * const p; //都不可变
const int fun(){}   //返回值是不可以被改变的

常成员函数

所有非常成员函数,都可以对数据成员进行修改,如果想让一个成员函数不能对数据成员修改,那么就要用到常成员函数实现

格式

函数返回值类型 函数名(形参列表)  const
{
    
}

代码示例

#include <iostream>

using namespace std;
//封装 学生 类
class Stu
{
private:
    string name;
    int age;
public:
    //无参构造函数
    Stu() {}
    
    //有参构造函数
    Stu(string n, int a):name(n),age(a)
    {}
    void show() const
    {
        //age = 78;  常成员函数不能修改数据成员的值
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
    }
};
int main()
{
    Stu s("zhangsan",3);
    s.show();
    return 0;
}

常对象

作用

  • 常对象表明这个对象的所有数据成员不能被改变
  • 常对象只能调用常成员函数,如果没有常成员函数,则报错
  • 非常对象对于常成员函数和非常成员函数都可以调用,优先调用非常成员函数
  • 常成员函数和非常成员函数构成重载(重载原因:this指针类型不同)

mutable关键字

  • mutable修饰变量----->取消常属性
  • mutable修饰数据成员,表示该数据可以在常成员函数中被修改

代码示例

#include <iostream>

using namespace std;
//封装 学生 类

class Stu
{
private:
    string name;
    mutable int age;  //在常成员函数中可以被修改
public:
    //无参构造函数
    Stu() {}

    //有参构造函数
    Stu(string n, int a):name(n),age(a)
    {}

    //常成员函数
    void show() const  //Stu const * const this   都不可变
    {
        age = 78;  //常成员函数不能修改数据成员的值
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
    }

int main()
{
   //非常对象
    Stu s("zhangsan",3);
    s.show();
    return 0;
}

运算符重载

概念

运算符重载就是对运算符重新定义,赋予另一种功能,以适应不同的数据类型
每个运算符重载都有两种实现方式:成员函数实现运算符重载、全局函数实现运算符重载

算数运算符的重载

  • 种类:+ - * / %
  • 表达式:L # R(L:左操作数,#运算符,R又操作数)
  • 左操作数:可以是左值,也可以是右值,在运算过程中不不会被改变
  • 右操作数:可以是左值,也可以是右值,在运算过程中不会被改变
  • 结果:右值(不可以被改变)

实现方式

1.成员函数的实现
		const 类名 operator#(const 类名 &R) const
		{}
	(1)const运算结果不能被改变
	(2)const右操作数在运算过程中,不能被改变
	(3)const左操作数在运算过程中,不能被改变
2.全局函数实现:
		const 类名 operator#(const 类名 &L,const 类名 &R)
		{}

代码示例

#include <iostream>

using namespace std;

//封装人  类
class Person
{
    friend const Person operator+(const Person &L, const Person &R);
private:
    int a;
    int b;
public:
    //无参构造函数
    Person() {}

    //有参构造函数
    Person(int a, int b):a(a),b(b)
    {}
    //成员函数实现 + 号运算符重载
//    const Person operator+(const Person &R) const
//    {
//        Person temp;
//        temp.a = a + R.a;
//        temp.b = b + R.b;

//        return temp;
//    }

    void display()
    {
        cout << "a = " << a << endl;
        cout << "b = " << b << endl;
    }
};
//全局函数实现+号运算符重载
const Person operator+(const Person &L, const Person &R)
{
    Person temp;
    temp.a = L.a + R.a;
    temp.b = L.b + R.b;

    return temp;
}

int main()
{
    Person p1(10,10);
    Person p2(10,10);

    //简化成:
    //Person p3 = p1 + p2;  //本质: p3 = p1.operator+(p2)
    Person p3 = p1 + p2;  //本质: p3 = operator+(p1,p2)

    p3.display();

    //Person p4 = p1.operator+(p2);
    //p4.display();
    return 0;
}

关系运算符的重载

  • 种类:> >= < <= == !=

代码实现

#include <iostream>

using namespace std;

//定义一个类
class Ope
{
    int a;
    int b;
public:
    //无参构造函数
    Ope()
    {}
    //有参构造函数
    Ope(int a,int b):a(a),b(b)
    {}
    //成员函数>关系运算
    bool operator>(const Ope &R) const
    {
        if(a>R.a && b>R.b)
            return true;
        else
            return false;
    }
    //成员函数<关系运算
    bool operator<(const Ope &R) const
    {
        if(a<R.a && b<R.b)
            return true;
        else
            return false;
    }
    //成员函数==关系运算
    bool operator==(const Ope &R) const
    {
        if(a==R.a && b==R.b)
            return true;
        else
            return false;
    }
};

int main()
{
    Ope p1(10,10);
    Ope p2(10,10);
    if(p1 > p2)
        cout << "p1>p2" << endl;
    if(p1 < p2)
        cout << "p1<p2" << endl;
    if(p1 == p2)
        cout << "p1=p2" << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值