C++ Day4

目录

一、拷贝赋值函数

1.1 作用

1.2 格式

二、匿名对象

 2.2 格式

三、友元

3.1作用

3.2格式

3.3 种类

3.4 全局函数做友元

 3.5类做友元

 3.6 成员函数做友元

3.7注意

四、常成员函数和常对象

4.1 常成员函数

4.1.1格式

示例: 

4.2 常对象

作用:

格式:

 示例:

4.3 mutable关键字

五、运算符重载

5.1概念

5.2 算术运算符的重载

 1.成员函数实现:

5.3 关系运算符的重载

5.4 赋值运算符重载

5.5自增、自减运算符重载

自增为例:

1)前置自增

2)后置自增

5.6插入、提取运算符重载

5.7 不能重载的运算符

作业:实现关系运算符的重载


一、拷贝赋值函数

1.1 作用

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

1.2 格式

一、拷贝赋值函数
1.1 作用
用一个对象给另一个对象赋值。
1.2 格式

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

#include <iostream>


using namespace std;


//封装 学生 类
class Stu
{
private:
    string name;
    int age;
public:
    //无参构造函数
    Stu() {cout << "无参构造函数" << endl;}


    //有参构造函数
    Stu(string name, int age):name(name),age(age)
    {cout << "有参构造函数" << endl;}


    //拷贝构造函数
    Stu(const Stu& other):name(other.name)
    {
        this->age = other.age;
        cout << "拷贝构造函数" << endl;
    }


    //拷贝赋值函数
    Stu & operator=(const Stu& other)
    {
        if(this != &other)  //避免自己给自己赋值
        {
            
            this->name = other.name;
            age = other.age;
            cout << "拷贝赋值函数"  << endl;
            
            
        }
            
            return *this;  //返回自己
        
    }
    ~Stu()
    {
        cout << "析构函数" << endl;
    }
    void display()
    {
        cout << name << endl;
    }
};




int main()
{
    Stu s1("zhangsan",12);
    s1.display();


    Stu s2 = s1;  // s2.Stu(s1)
    s2.display();


    Stu s3;
    s3 = s1;  //s3.operator=(s1)
    s3.display();


    return 0;
}

二、匿名对象

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

用处:

1.用匿名对象给有名对象初始化

2.用匿名对象个对象数组初始化

3.用匿名对象做函数实参。

 2.2 格式

类名()

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

三、友元

3.1作用

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

3.2格式

friend xxxxxx

3.3 种类

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

3.4 全局函数做友元

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

 3.5类做友元

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

 3.6 成员函数做友元

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

3.7注意

1.不要过度的使用友元,会降低封装性。

2.友元不具有交换性、传递性、继承性。

四、常成员函数和常对象

热知识:

const int a = 10; //a不能被改变

int const *p; //指针的指向可变,指向里的值不可变

int * const p; // 指针的指向不可变,指向里的值可变

int const * const p; //都不可变

const int fun(){}  //返回值是不可以被改变的

4.1 常成员函数

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

4.1.1格式

函数返回值类型 函数名(形参列表)  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;
}

4.2 常对象

作用:

常对象,表明这个对象的所有数据成员不能被改变。

常对象只能调用常成员函数,如果没有常成员函数,则报错。

非常对象对于常成员函数和非常成员函数都可以调用,优先非常成员函数。

常成员函数和非常成员函数构成重载,原因this指针类型不同。

格式:

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  //Stu const * const this   都不可变
    {
        //age = 78;  常成员函数不能修改数据成员的值
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
    }

    //非常成员函数
    void show()   // Stu * const this  指向不可变 指向的值可以变
    {
        age = 78;
        cout << "姓名:" << name << endl;
        cout << "年龄:" << age << endl;
    }
};

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

    //常对象
    const Stu s1("lisi",4);
    s1.show();
    return 0;
}

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


//    //非常成员函数
//    void show()   // Stu * const this  指向不可变 指向的值可以变
//    {
//        age = 78;
//        cout << "姓名:" << name << endl;
//        cout << "年龄:" << age << endl;
//    }
};

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

//    //常对象
//    const Stu s1("lisi",4);
//    s1.show();
    return 0;
}

五、运算符重载

5.1概念

运算符重载 就是对运算符重新定义,赋予另一种功能,以适应不同的数据类型。

每个运算符重载都有两种实现方式:成员函数实现运算符重载、全局函数实现运算符重载

5.2 算术运算符的重载

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

 1.成员函数实现:


const 类名 operator#(const 类名 &R) const

{}

// 1. cosnt 运算结果不能被改变

2.cosnt 右操作数在运算过程中,不能被改变

3.cosnt 左操作数在运算过程中,不能被改变

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

5.3 关系运算符的重载

1> 种类:> >= <

2> 表达式: L # R ( L:左操作数 #运算符 R: 右操作数)

3> 左操作数:可以是左值,也可以是右值,在运算过程中 不会被改变

4> 右操作数:可以是左值,也可以是右值,在运算过程中 不会被改变

5> 结果:bool类型

6> 实现方式

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

5.4 赋值运算符重载

1> 种类:= 、+=、-=、*=、/=、%=

2> 表达式: L # R ( L:左操作数 #运算符 R: 右操作数)

3> 左操作数:只能是左值

4> 右操作数:可以是左值,也可以是右值,在运算过程中 不会被改变

5> 结果:自身的引用

6> 实现方式

1.成员函数实现:
         类名 & operator#(const 类名 &R)
 {}
   
2.全局函数实现:
       类名 &  operator#(类名 &L, const 类名 &R)
      {}

5.5自增、自减运算符重载

自增为例:

1)前置自增

1.表达式 :++O

2.操作数:左值,运算过程中要被改变

3.结果:自身的引用

4.实现方式:
      成员函数实现:  类名 & operator++()
      全局函数实现:   类名 & operator++(类名 &O)

2)后置自增

1.表达式 :O++

2.操作数:左值,运算过程中要被改变

3.结果:右值 (不可以被改变)

4.实现方式:
      成员函数实现:  const 类名 operator++(int)
      全局函数实现:   const 类名 operator++(类名 &O,int)
#include <iostream>

using namespace std;

//封装人  类
class Person
{
//    friend const Person operator+(const Person &L, const Person &R);
    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(const Person& p):a(p.a),b(p.b)
    {

    }

    //成员函数实现 + 号运算符重载
    const Person operator+(const Person &R) const
    {
        Person temp;
        temp.a = a + R.a;
        temp.b = b + R.b;

        return temp;
    }

    //成员函数实现 >浩运算符重载
    bool operator>(const Person &R)
    {
        if(a>R.a && b>R.b)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    //成员函数实现+=运算符重载
//    Person & operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a;
//        b += R.b;
//        return *this;
//    }

    //成员函数实现前++运算符重载
    Person & operator++()
    {
        ++a;
        ++b;
        return *this;
    }

    //成员函数实现后++运算符重载
    const Person operator++(int)  //区别前置自增
    {
        Person temp;
        temp.a = a++;
        temp.b = 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;
//}


//全局函数实现+=运算符重载
Person & operator+=(Person &L, const Person &R)
{
    L.a += R.a;
    L.b += R.b;
    return L;
}

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();

    if(p3>p1)
    {
        cout << "p3>p1" << endl;
    }

    cout << "=======================" << endl;

    Person p4(3,4);
    p4 += p1;
    p4.display();

    cout << "=======================" << endl;

    p1 = ++p4;
    p1.display();
    p4.display();

    cout << "=======================" << endl;

    Person p5(7,8);
    p2 = p5++;
    p2.display();
    p5.display();



    return 0;
}

5.6插入、提取运算符重载

插入 >

cout 是 ostream 类的对象

cin 是 istream 类的对象

#include <iostream>

using namespace std;

//封装人  类
class Person
{
//    friend const Person operator+(const Person &L, const Person &R);
    friend Person & operator+=(Person &L, const Person &R);
    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)
    {}

    Person(const Person& p):a(p.a),b(p.b)
    {

    }

    //成员函数实现 + 号运算符重载
    const Person operator+(const Person &R) const
    {
        Person temp;
        temp.a = a + R.a;
        temp.b = b + R.b;

        return temp;
    }

    //成员函数实现 >浩运算符重载
    bool operator>(const Person &R)
    {
        if(a>R.a && b>R.b)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    //成员函数实现+=运算符重载
//    Person & operator+=(const Person &R)
//    {
//        a += R.a; // a = a + R.a;
//        b += R.b;
//        return *this;
//    }

    //成员函数实现前++运算符重载
    Person & operator++()
    {
        ++a;
        ++b;
        return *this;
    }

    //成员函数实现后++运算符重载
    const Person operator++(int)  //区别前置自增
    {
        Person temp;
        temp.a = a++;
        temp.b = 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;
//}


//全局函数实现+=运算符重载
Person & operator+=(Person &L, const Person &R)
{
    L.a += R.a;
    L.b += R.b;
    return L;
}

//全局函数实现插入运算符重载
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;
   cin >> p.b;
   return cin;
}

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();

    if(p3>p1)
    {
        cout << "p3>p1" << endl;
    }

    cout << "=======================" << endl;

    Person p4(3,4);
    p4 += p1;
    p4.display();

    cout << "=======================" << endl;

    p1 = ++p4;
    p1.display();
    p4.display();

    cout << "=======================" << endl;

    Person p5(7,8);
    p2 = p5++;
    p2.display();
    p5.display();


    cout << "=======================" << endl;
    // operator<<(cout,p2)
    cout << p2 << endl;  //本质   cout.perator<<(p2)
                         //全局函数本质 operator<<(cout,p2)
                         // ostream &   operator<<(ostream &cout,const Person &p)


    cout << "=======================" << endl;
    Person p6;
    cin >> p6;  //cin.operator>>(p2)
                // operator>>(cin,p6)
                // istream & operator>>(istream &cin, Person & p)
    cout << p6;




    return 0;
}

5.7 不能重载的运算符

  • 成员运算符 .
  • 成员指针运算符 ->
  • 作用域限定符 ::
  • 计算字节大小 sizeof()
  • 三目运算符 ? :

作业:实现关系运算符的重载

#include <iostream>

using namespace std;

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

    Stu(int a): a(a)
    {

    }
    //成员函数实现+号运算符重载
    bool operator > (const  Stu &R) const
    {
        return a > R.a;
    }
    bool operator >= (const  Stu &R) const
    {
        return a >= R.a;
    }
    bool operator < (const  Stu &R) const
    {
        return a < R.a;
    }
    bool operator <= (const  Stu &R) const
    {
        return a <= R.a;
    }
    bool operator == (const  Stu &R) const
    {
        return a == R.a;
    }
    bool operator != (const  Stu &R) const
    {
        return a != R.a;
    }

};


int main()
{
    Stu s1(10);
    Stu s2(100);
    cout << (s1>s2) << endl;
    cout << (s1>=s2) << endl;
    cout << (s1<=s2) << endl;
    cout << (s1<s2) << endl;
    cout << (s1==s2) << endl;
    cout << (s1!=s2) << endl;
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ck钉钉钉

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

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

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

打赏作者

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

抵扣说明:

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

余额充值