C++ DAY4

一、拷贝赋值函数

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


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

例如

#include 
 
 
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.用匿名对象做函数实参

格式:

类名()
#include 
 
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种

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

全局函数做友元

#include 
 
 
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 
 
 
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 
 
using namespace std;
 
 
class Room;//声明有这样的类
 
 
//类做友元
class GoodGay
{
public:
    Room *r;
    void visit();//在类内声明
    GoodGay();
     ~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;
}
 
GoodGay::~GoodGay()
{
    delete r;
}


int main()
{
 
 
    GoodGay g;
    g.visit();
 
 
    return 0;
}
 
 

 注意 友元的过多使用会降低封装性。且不具备交换性 。继承性。传递性(哪怕是间接能访问到,但也不能直接去访问)

四、常成员函数和常对象

常成员函数(没有加const后缀的函数即是非常成员函数)

使类中的数据成员不受修改

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

要点

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

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

常对象

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

const 类名 对象名;

要点

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

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

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

 mutable关键字

用来取消常属性,用该关键字修饰的数据成员可以在常成员函数中被修改

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

 五、算数运算符重载

对运算符赋予新定义,编译器会在同一类进行运算时去将运算符转为operator#(#代表运算符)去类中寻找对应的重载函数

这两种写法一致

    Complex end1 =c1.operator+(c2) ;  // 使用重载的 + 运算符
    Complex end2=c1 + c2;
每个运算符重载都有两种实现方式:成员函数实现运算符重载、全局函数实现运算符重载 
#include  
 
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 

class MyClass {
public:
    int value;

    MyClass(int val) : value(val) {}

    // 重载 == 运算符
    bool operator==(const MyClass& other) const {
        return value == other.value;
    }

    // 重载 != 运算符
    bool operator!=(const MyClass& other) const {
        return value != other.value;
    }

    // 重载 < 运算符
    bool operator<(const MyClass& other) const {
        return value < other.value;
    }

    // 重载 <= 运算符
    bool operator<=(const MyClass& other) const {
        return value <= other.value;
    }

    // 重载 > 运算符
    bool operator>(const MyClass& other) const {
        return value > other.value;
    }

    // 重载 >= 运算符
    bool operator>=(const MyClass& other) const {
        return value >= other.value;
    }
};

int main() {
    MyClass obj1(10);
    MyClass obj2(10);

    if (obj1 == obj2) {
        std::cout << "obj1 and obj2 are equal.\n";//==
    } else {
        std::cout << "obj1 and obj2 are not equal.\n";//!=
    }


    if (obj1 <= obj2) {
        std::cout << "true\n";
    } else {
        std::cout << "false\n";
    }
    if (obj1 >= obj2) {
        std::cout << "true\n";
    } else {
        std::cout << "false\n";
    }


    if (obj1 < obj2) {
        std::cout << "true\n";
    } else {
        std::cout << "false\n";
    }
    if (obj1 > obj2) {
        std::cout << "true\n";
    } else {
        std::cout << "false\n";
    }
    return 0;
}

 六、赋值运算符重载

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

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

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

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

5> 结果:自身的引用

6> 实现方式

1.成员函数实现:

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

{}

2.全局函数实现:

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

{}

以自增为例

1)前置自增
1.表达式 :++O
2.操作数:左值,运算过程中要被改变
3.结果:自身的引用
4.实现方式:
      成员函数实现:  类名 & operator++()
      全局函数实现:   类名 & operator++(类名 &O)
2)后置自增
1.表达式 :O++
2.操作数:左值,运算过程中要被改变
3.结果:右值 (不可以被改变)
4.实现方式:
      成员函数实现:  const 类名 operator++(int)
      全局函数实现:   const 类名 operator++(类名 &O,int)
 
#include  
 
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; 
} 

七、不能重载的运算符

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

你可能感兴趣的:(c++,开发语言)