嵌入式养成计划-38----C++--匿名对象--友元--常成员函数和常对象--运算符重载

八十七、匿名对象

  • 概念:没有名字对象
  • 格式 :类名();
  • 作用
    1. 用匿名对象给有名对象初始化的
    2. 用匿名对象给对象数组初始化的
    3. 匿名对象作为函数实参使用

示例 :

#include <iostream>
using namespace std;
class Dog
{
private:
    string name;
    string color;
    int *age;
public:
    //无参构造函数
    Dog()
    {
        cout << "Dog::无参构造函数" << endl;
    }
    //有参构造函数
    Dog(string name, string c, int age):name(name),color(c),age(new int(age))
    {
        cout << "Dog::有参构造函数" << endl;
    }
    //拷贝构造函数
    Dog(const Dog &other):name(other.name),color(other.color),age(new int(*other.age))
    {
        cout << "Dog::拷贝构造函数" << endl;
    }
    //拷贝赋值函数
    Dog &operator=(const Dog &other)
    {
        if(this != &other)  //避免自己给自己赋值
        {
            name = other.name;
            color = other.color;
            age = new int(*other.age); //深拷贝赋值函数
        }
        cout << "Dog::拷贝赋值函数" << endl;
        return *this;
    }
    //析构函数
    ~Dog()
    {
        cout << "Dog::析构函数" << endl;
    }
};
void fun(Dog g)//Dog g = Dog("大黄","lll",6)
{
    //函数代码。。。
}
int main()
{
    Dog d1 = Dog("大黄","lll",6); //匿名对象给有名对象初始化
    Dog d[3] = {Dog("大","lll",6),Dog("黄","lll",6),Dog("大黄","lll",6)};
    
    fun(Dog("大黄","lll",6));  //匿名对象作为函数实参使用
    return 0;
}

八十八、友元

88.1 作用

  • 可以让其他一些函数或者类访问 另一个类的私有数据成员
  • 友元关键字 : friend

88.2 种类

  1. 全局函数做友元
  2. 类友元
  3. 成员函数做友元

88.3 全局函数做友元

  • 让全局函数访问一个类私有数据成员。

示例 :

#include <iostream>
using namespace std;
class Room {
    friend void room_friend(Room &r);
private:
    string keting;
public:
    string zoulang;

    Room();
};
Room::Room(){
    this->keting = "客厅";
    this->zoulang = "走廊";
}
void room_friend(Room &r){
    cout << "全局友元函数在访问->" << r.zoulang <<endl;
    cout << "全局友元函数在访问->" << r.keting <<endl;
}
int main()
{
    Room r1;
    room_friend(r1);
    return 0;
}

88.4 类做友元

  • 一个类去访问另一个类的私有属性。

88.5 成员函数做友元

  • 一个类里的成员函数去访问另一个类的私有属性。

88.6 示例

#include <iostream>
using namespace std;

class Room;

class Friend_Room{
private:
    Room *r;
public:
    Friend_Room();
    void access_room();
};

class Room {
//    friend class Friend_Room;
    friend void Friend_Room::access_room();
private:
    string keting;
public:
    string zoulang;
    
    Room();
};
Room::Room(){
    this->keting = "客厅";
    this->zoulang = "走廊";
}

Friend_Room::Friend_Room(){
    this->r = new Room;
    cout << "Friend_Room 的 构造函数" << endl;
}
void Friend_Room::access_room(){
    cout << "Friend_Room 正在访问 " << this->r->zoulang << endl;
    cout << "Friend_Room 正在访问 " << this->r->keting << endl;
}

int main()
{
    Friend_Room f_r;
    f_r.access_room();
    return 0;
}

88.7 注意

  • 不要过度使用友元,会降低或者破坏封装性
  • 友元不具有交互性,传递性,继承性。

八十九、const修饰的成员函数和对象(常成员函数、常对象)

  • 类中所有的成员函数都可以对类中数据成员进行修改操作,
  • 如果想设计一个成员函数不能对数据成员修改操作,则需要用const修饰的成员函数实现。

89.1 常成员函数

  • 常成员函数 :表示该成员函数不能修改数据成员的值。
  • 格式 :
    返回值类型 函数名(形参列表) const 
    {
        函数体内容;
    }
    
  • 同名的常成员函数和非常成员函数构成重载关系,
    • 原因:this指针类型不同

89.2 常对象

  • 常对象表示这个对象的数据成员不能被修改。
  • 格式: const 类名 对象名;
  1. 非常对象可以调用常成员函数,也可以调用非常成员函数,优先调用非常成员函数
  2. 常对象只能调用常成员函数,如果没有常成员函数,则报错

示例 :

#include <iostream>
using namespace std;

class Stu
{
private:
    string name;
    int id;
public:
    Stu(){}
    Stu(string  name, int id):name(name),id(id)
    {}
    //常成员函数
    void display() const //this指针原型: Stu const * const this;
    {
        //this->name = "lisi"; 常成员函数不能对数据成员修改
        cout << name <<"  "  << id << endl;
    }
    //非常成员函数
    void display() //this指针原型: Stu * const this;
    {
        this->name = "lisi";
        cout << name <<"  "  << id << endl;
    }
};
int main()
{
    const Stu s1("zhangsan", 1001);   //常对象
    s1.display(); //常对象只能调用常成员函数


    return 0;
}

89.3 mutable关键字

  • mutable修饰成员变量,表示该成员变量可以在常成员函数中被修改 (取消常属性)
    在这里插入图片描述

九十、运算符重载

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

90.1 算术运算符重载

种类: +  -   *  /    %
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:右值 (不可以被改变)
  • 算术运算符重载实现方式:
    1. 成员函数实现运算符重载

      const 类名 operator(const 类名 &R) const 
      {
      	具体实现
      }
      

      第一个const 表示结果是右值 不能被改变
      第二个const 表示右操作数运算过程中不能被改变
      第三个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 &p) const
//    {
//        Person temp;
//        temp.a = a + p.a;
//        temp.b = b + p.b;
//        return temp;
//    }
    void show()
    {
        cout << " a = " << a << "    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; //本质上 Person p3 = p1.operator+(p2)
    Person p3 = p1 + p2; //本质上 Person p3 = operator+(p1, p2)
    p3.show();
    return 0;
}

90.2 关系运算符重载

种类: > 、 >= 、 <、 <=、  ==、  !=
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:可以是左值,可以右值,运算过程中不可以被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果: bool类型
  • 关系运算符重载实现方式:
    1. 成员函数实现运算符重载
      bool operator(const 类名 &R) const
      {
      	具体实现
      }
      
    2. 全局函数实现运算符重载
      bool operator(const 类名 &L, const 类名 &R)
      {
      	具体实现
      }
      

示例 :

#include <iostream>
using namespace std;
//
class Person
{
    friend bool operator>(const Person &L, const Person &R);
private:
    int a;
    int b;
public:
    Person(){}
    Person(int a, int b):a(a),b(b){}
    //成员函数实现>号运算符重载
//    bool operator>(const Person &R) const
//    {
//        if(a>R.a && b>R.b)
//        {
//            return true;
//        }
//        else
//        {
//            return false;
//        }
//    }
    void show()
    {
        cout << " a = " << a << "    b = " << b << endl;
    }
};
//全局函数实现>号运算符重
bool operator>(const Person &L, const Person &R)
{
    if(L.a>R.a && L.b>R.b)
    {
        return true;
    }
    else
    {
        return false;
    }
}
int main()
{
    Person p1(10,10);
    Person p2(10,10);
    if(p3 > p2)  //本质上  p3.operator>(p2)
    //本质上 operator(p3,p2)
    {
        cout <<"p3>p2" << endl;
    }
    return 0;
}

90.3 赋值运算符重载

种类: = 、+= 、 -= 、*= 、/=  、%=
表达式: L   ?   R    (L 左操作数     ?运算符    R右操作数)
左操作数:是左值,运算过程中要被改变
右操作数:可以是左值,可以右值,运算过程中不可以被改变
结果:自身的引用
  • 赋值运算符重载实现方式:
    1. 成员函数实现运算符重载
      类名 &operator(const 类名 &R) 
      {
      	具体实现
      }
      
    2. 全局函数实现运算符重载
      类名 &operator(类名 &L, const 类名 &R) 
      {
      	具体实现
      }
      

示例 :

#include <iostream>
using namespace std;

class Person
{
    friend Person &operator+=(Person &L,const Person &R);
private:
    int a;
    int b;
public:
    Person(){}
    Person(int a, int b):a(a),b(b){}
    //成员函数实现+=号运算符重载
//    Person &operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a
//        b += R.b;
//        return *this;
//    }
    void show()
    {
        cout << " a = " << a << "    b = " << b << endl;
    }
};
//全局函数实现+=号运算符重载
Person &operator+=(Person &L,const Person &R)
{
    L.a += R.a; // a = a + R.a
    L.b += R.b;
    return L;
}
int main()
{
    Person p1(10,10);
    Person p2(10,10);
    p3+=p2;  //  p3 = p3 + p2    本质上 p3.operator+=(p2)
    p3.show();
    return 0;
}

90.4 自增、自减运算符重载

  • ++、- -
  • 下面以自增为例,自减的话,换下符号就行了
  • 前置自增
表达式	:	++O
操作数	:	左值,运算过程中要改变
结果	:	左值  自身的引用

前置自增运算符重载实现方式:

  1. 成员函数实现运算符重载
    类名 &operator++()
    {}
    
  2. 全局函数实现运算符重载
    类名 &operator++(类名 &O)
    {}
    
  • 后置自增
表达式	:	O++
操作数	:	左值,运算过程中要改变
结果	:	右值,不可以被改变

后置自增运算符重载实现方式:

  1. 成员函数实现运算符重载
    const 类名 operator++(int)  //
    {}
    
  2. 全局函数实现运算符重载
    const 类名 operator++( 类名 &O, int)
    {}
    

示例 :

#include <iostream>
using namespace std;
class Person
{
    friend Person &operator++(Person &O);
private:
    int a;
    int b;
public:
    Person(){}
    Person(int a, int b):a(a),b(b)
    {}
    //成员函数实现前++号运算符重载
//    Person &operator++()
//    {
//        ++a;
//        ++b;
//        return *this;
//    }
    //成员函数实现后++号运算符重载
    const Person operator++(int) // int 哑元 占位作用
    {
        Person temp;
        temp.a = a++;
        temp.b = b++;
        return temp;
    }
    void show()
    {
        cout << " a = " << a << "    b = " << b << endl;
    }
};
//全局函数实现前++号运算符重载
Person &operator++(Person &O)
{
    ++O.a;
    ++O.b;
    return O;
}
int main()
{
    Person p1(10,10);
    Person p2(10,10);
    p2 = ++p3;    //本质上 p3.operator++()
                  //operator++(p3)
    p3.show();
    p2.show();
    cout << "===================="  << endl;
    p1 = p3++;  // p1 = p3  p1 = p3.operator++()
    p1.show();
    p3.show();
    return 0;
}

90.5 插入、提取运算符重载

  • 插入符 << (或者叫输出符)
  • 提取符 >> (或者叫输入符)
  • cout 是ostream 类对象,可以换成别的名字
  • cin 是 istream类对象,可以换成别的名字

示例 :

#include <iostream>
using namespace std;
class Person
{
    friend ostream &operator<<(ostream &cout, const Person &p);
    friend istream &operator>>(istream &cin, Person &p);
private:
    int a;
    int b;
public:
    Person() {}
    Person(int a, int b):a(a),b(b) {}
    void show()
    {
        cout << " a = " << a << "    b = " << b << endl;
    }
};
//全局函数实现插入<<运算符重载
ostream &operator<<(ostream &cout, const Person &p)
{
    cout << p.a << endl;
    cout << p.b << endl;
    return cout;
}
//全局函数实现提取>>运算符重载
istream &operator>>(istream &cin, Person &p)
{
    cin >> p.a >> p.b;
    return cin;
}
int main()
{
    Person p1(10,10);
    Person p2(10,10);
    //cout  -- ostream
    cout << p3 << p2 << endl; //成员函数本质上  cout.operator<<(p3)
                              //全局函数本质 operator<<(cout, p3)
                              //----> ostream &   operator<<(ostream &cout,const Person &p)
    //cin >> a >> b;
    cout << "===================="  << endl;
    Person p;
    cin >> p;  //成员函数本质上  cin.operator>>(p)
           //全局函数本质 operator>>(cin, p)
           //----> istream & operator>>(istream &cin, Person &p)
    cout << p;
    return 0;
}

90.6 不可以重载的运算符

访问成员   .
指针访问成员  ->
作用域限定符  ::
三目运算符  ? :
sizeof() 
...
..
.  

小作业

  • 整理代码
    • 算术运算符
    • 逻辑运算符
    • 赋值运算符

我写的

#include <iostream>

using namespace std;

class Stu {
    //逻辑运算符重载的全局友元函数
    friend bool operator>(const Stu &l, const Stu &r);
    friend bool operator>=(const Stu &l, const Stu &r);
    friend bool operator<(const Stu &l, const Stu &r);
    friend bool operator<=(const Stu &l, const Stu &r);
    friend bool operator==(const Stu &l, const Stu &r);
    friend bool operator!=(const Stu &l, const Stu &r);

    //赋值运算符重载
    friend Stu &operator+=(Stu &l, const Stu &r);
    friend Stu &operator-=(Stu &l, const Stu &r);
    friend Stu &operator*=(Stu &l, const Stu &r);
    friend Stu &operator/=(Stu &l, const Stu &r);
    friend Stu &operator%=(Stu &l, const Stu &r);
private:
    double high;
    double weight;
public:
    Stu(){}
    Stu(double h, double w):high(h),weight(w){}
    void show(){
        cout << "high = " << this->high << endl;
        cout << "weight = " << this->weight << endl;
        puts("");
    }

    //类内实现运算符重载
    //算术运算符重载
    const Stu operator+(const Stu &s)const{
        Stu t;
        t.high = this->high + s.high;
        t.weight = this->weight + s.weight;
        return t;
    }
    const Stu operator-(const Stu &s)const{
        Stu t;
        t.high = this->high + s.high;
        t.weight = this->weight + s.weight;
        return t;
    }

    const Stu operator*(const Stu &s)const{
        Stu t;
        t.high = this->high + s.high;
        t.weight = this->weight + s.weight;
        return t;
    }

    const Stu operator/(const Stu &s)const{
        Stu t;
        t.high = this->high + s.high;
        t.weight = this->weight + s.weight;
        return t;
    }

    const Stu operator%(const Stu &s)const{
        Stu t;
        t.high = (int)this->high % (int)s.high;
        t.weight = (int)this->weight % (int)s.weight;
        return t;
    }

    //重载赋值运算符
    const Stu &operator=(const Stu &s){
        this->high = s.high;
        this->weight = s.weight;
        return *this;
    }
};

/*
 * 全局函数实现运算符重载
 * 访问类的私有属性需要添加为类的友元函数
*/
//逻辑运算符重载
bool operator>(const Stu &l, const Stu &r){
    if(l.high > r.high && l.weight > r.weight)
        return true;
    return false;
}
bool operator>=(const Stu &l, const Stu &r){
    if(l.high >= r.high && l.weight >= r.weight)
        return true;
    return false;
}
bool operator<(const Stu &l, const Stu &r){
    if(l.high < r.high && l.weight < r.weight)
        return true;
    return false;
}
bool operator<=(const Stu &l, const Stu &r){
    if(l.high <= r.high && l.weight <= r.weight)
        return true;
    return false;
}
bool operator==(const Stu &l, const Stu &r){
    if(l.high == r.high && l.weight == r.weight)
        return true;
    return false;
}
bool operator!=(const Stu &l, const Stu &r){
    if(l.high != r.high && l.weight != r.weight)
        return true;
    return false;
}


//赋值运算符重载
Stu &operator+=(Stu &l, const Stu &r){
    l.high += r.high;
    l.weight += r.weight;
    return l;
}
Stu &operator-=(Stu &l, const Stu &r){
    l.high -= r.high;
    l.weight -= r.weight;
    return l;
}
Stu &operator*=(Stu &l, const Stu &r){
    l.high *= r.high;
    l.weight *= r.weight;
    return l;
}
Stu &operator/=(Stu &l, const Stu &r){
    l.high /= r.high;
    l.weight /= r.weight;
    return l;
}
Stu &operator%=(Stu &l, const Stu &r){
    l.high  = (int)l.high % (int)r.high;
    l.weight = (int)l.weight % (int)r.weight;
    return l;
}

int main()
{
    Stu s1(175, 60);
    Stu s2(170, 55);

    Stu s3 = s1 + s2;
    Stu s4 = s1 - s2;
    Stu s5 = s1 * s2;
    Stu s6 = s1 / s2;
    Stu s7 = s1 % s2;

    s1.show();
    s2.show();
    s3.show();
    s4.show();
    s5.show();
    s6.show();
    s7.show();

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhk___

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值