QT学习C++(12)

本文详细介绍了C++中运算符重载的概念和实践,包括友元函数和成员函数两种方式来实现运算符重载,如`<<`、`+`等。同时展示了自增、自减、指针、赋值、等于和不等于运算符的重载。还讨论了字符串类的设计,包括重载`[]`、`<<`和`>>`运算符。此外,提到了如何处理类中包含指针成员时的赋值运算符重载问题,以及仿函数的概念。
摘要由CSDN通过智能技术生成

运算符重载

目的:简化操作,让已有运算符适应不同类型的数据。

语法:函数的名字由关键字operator及其紧跟的运算符组成

例如:“+”运算符的重载:operator+

运算符<<的重载( 全局函数作为友元,完成运算符重载)

#include <iostream>
#include <string.h>
using namespace std;
class Mem{
    //设置重载函数为友元函数
    friend void operator<<(ostream &out, Mem &P);
private:
    char* name;
    int age;
public:
    Mem(char* name, int age){
        this->name = new char[strlen(name)+1];
//        this->name = name;
        strcpy(this->name, name);
        this->age = age;
    }
    ~Mem(){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
    }
    void Print(){
        cout << "name: " << this->name <<endl;
        cout << "age: " << this->age << endl;
    }
};
void operator<<(ostream &out, Mem &P){
    out << "name: " << P.name << endl;
    out << "age: " << P.age << endl;
}
int main()
{
    Mem Lucy("lucy", 18);
    //调用普通成员函数遍历对象
    Lucy.Print();
    cout << endl;
    //cout默认输出方式,无法输出对象,无法识别自定义对象格式
//    cout << Lucy << endl;
//    cout << Lucy.Print() << endl;
    //重载<<
    //运算符重载的调用方式1:
    operator<<(cout, Lucy);
    cout << endl;
    //运算符重载的调用方式2:
    /*对方法1的优化,去掉operator
     第一个参数放在运算符<<的左边
     第二个参数放在运算符<<的右边
     */
    cout << Lucy;
    return 0;
}

 升级版

返回cout的引用,可以实现迭代操作

#include <iostream>
#include <string.h>
using namespace std;
class Mem{
    //设置重载函数为友元函数
    friend ostream& operator<<(ostream &out, Mem &P);
private:
    char* name;
    int age;
public:
    Mem(char* name, int age){
        this->name = new char[strlen(name)+1];
//        this->name = name;
        strcpy(this->name, name);
        this->age = age;
    }
    ~Mem(){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
    }
    void Print(){
        cout << "name: " << this->name <<endl;
        cout << "age: " << this->age << endl;
    }
};
ostream& operator<<(ostream &out, Mem &P){
    out << "name: " << P.name << endl;
    out << "age: " << P.age << endl;
    return cout;
}
int main()
{
    Mem Lucy("lucy", 18);
    Mem Rex("rex", 20);
    //可以实现迭代操作
    cout << Lucy << Rex << endl;
    return 0;
}

 运算符+的重载(全局函数作为友元,完成运算符重载)

#include <iostream>
#include <string.h>
using namespace std;
class Mem{
    //设置重载函数为友元函数
    friend ostream& operator<<(ostream &out, Mem &P);
    friend Mem operator+(Mem &P1, Mem &P2);
private:
    char* name;
    int age;
public:
    Mem(char* name, int age){
        this->name = new char[strlen(name)+1];
//        this->name = name;
        strcpy(this->name, name);
        this->age = age;
    }
    ~Mem(){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
    }
    void Print(){
        cout << "name: " << this->name <<endl;
        cout << "age: " << this->age << endl;
    }
};
ostream& operator<<(ostream &out, Mem &P){
    out << "name: " << P.name << endl;
    out << "age: " << P.age << endl;
    return cout;
}
Mem operator+(Mem &P1, Mem &P2){
    char* name = new char[strlen(P1.name)+strlen(P2.name)+1];
    name = strcat(P1.name, P2.name);
    int age = P1.age + P2.age;
    Mem N(name, age);
    if(name != NULL){
        delete [] name;
        name = NULL;
    }
    return N;
}
int main()
{
    Mem Lucy("lucy", 18);
    Mem Rex("rex", 20);
    //可以实现迭代操作
    Mem New = Lucy + Rex;
    cout << New << endl;
    return 0;
}

  运算符+的重载(成员函数完成运算符重载)

#include <iostream>
#include <string.h>
using namespace std;
class Mem{
    //设置重载函数为友元函数
    friend ostream& operator<<(ostream &out, Mem &P);
private:
    char* name;
    int age;
public:
    Mem(char* name, int age){
        this->name = new char[strlen(name)+1];
//        this->name = name;
        strcpy(this->name, name);
        this->age = age;
    }
    ~Mem(){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
    }
    void Print(){
        cout << "name: " << this->name <<endl;
        cout << "age: " << this->age << endl;
    }
    //成员函数完成运算符重载
    Mem operator+(Mem &P2){
        char* name = new char[strlen(this->name)+strlen(P2.name)+1];
        name = strcat(this->name, P2.name);
        int age = this->age + P2.age;
        Mem N(name, age);
        if(name != NULL){
            delete [] name;
            name = NULL;
        }
        return N;
    }
};
ostream& operator<<(ostream &out, Mem &P){
    out << "name: " << P.name << endl;
    out << "age: " << P.age << endl;
    return cout;
}

int main()
{
    Mem Lucy("lucy", 18);
    Mem Rex("rex", 20);
    //方法1
//    Mem New = Lucy.operator+(Rex);
    //方法2
    Mem New = Lucy + Rex;
    cout << New << endl;
    return 0;
}

 

自增和自减运算符的重载 

自增运算符的重载

#include <iostream>
#include <string.h>
using namespace std;
class Mem{
    friend ostream& operator<<(ostream &out, Mem &P);
private:
    int a;
    int b;
public:
    Mem(int a, int b):a(a), b(b){}
    ~Mem(){}
    //成员函数完成运算符重载
    //重载前置++,先+,后使用
    //编译器默认识别operator++(a),使用成员函数作为重载可用this,因此可简化为operator++()
    Mem& operator++(){
        //先加
        a++;
        b++;
        //后使用
        return *this;
    }
    //重载后置++,先使用,后+
    //编译器默认识别operator++(a, int),使用成员函数作为重载可用this,因此可简化为operator++(int)
    Mem operator++(int){
        //先加
        Mem old(a, b);
        a++;
        b++;
        //后使用
        return old;
    }
};
ostream& operator<<(ostream &out, Mem &P){
    out << "a: " << P.a << endl;
    out << "b: " << P.b << endl;
    return cout;
}

int main()
{
    Mem age(20, 18);
    cout << ++age;
    cout << endl;
    Mem b = age++;
    cout << b;
    cout << endl;
    cout << age;
    return 0;
}

自减运算符的重载(和自增运算符的重载相似)

指针运算符(*, ->)的重载

#include <iostream>
#include <string.h>
using namespace std;
class Age{
private:
    int num;
public:
    Age(int num): num(num){
        cout << "GZ_age= " << num << endl;
    }
    void show(){
        cout << "age= " << num << endl;
    }
    ~Age(){
        cout << "XG_age= " << num << endl;
    }
};
class Pointer{
public:
    Age* age;
public:
    Pointer(Age* age): age(age){
        cout << "GZ2" << endl;
        age->show();
    }
    ~Pointer(){
        age->show();
        if(age != NULL){
            delete this->age;
            this->age = NULL;
            cout << "XG2" << endl;
        }
    }
    Age* operator->(){
        return this->age;
    }
    Age& operator*(){
        return *(this->age);
    }
};
int main()
{
    Age A(1);
    //B指针并没有被释放,需要 delete B;
    Age* B = new Age(2);
    //可以自动设置指针并释放
    Pointer C(new Age(3));
    //想要访问Age类中的show()函数
    //C.age->show();
    //使用重载的->简化C.age->show();
    C->show();
    //等于(C.operator->())->show();

    //使用重载的*简化访问show();
    (*C).show();
    return 0;
}

赋值运算符(=)的重载(重要

前提1:类中无指针成员不需要重载=运算符

#include <iostream>

using namespace std;
class Arr{
public:
    int a;
    int b;
public:
    Arr(): a(0), b(0){
        cout << "WC_GZ" << endl;
    }
    Arr(int a, int b): a(a), b(b){
        cout << "YG_GZ" << endl;
    }
    Arr(const Arr &arr): a(arr.a), b(arr.b){
        cout << "KB_GZ" << endl;
    }
    ~Arr(){
        cout << "XGHS" << endl;
    }
    void show(){
        cout << "a= " << a << " b= " << b << endl;
    }
};
int main()
{
    Arr A(1, 2);
    A.show();
    //这里A对B赋值调用的拷贝构造函数,这里=并不是赋值运算符=
    Arr B = A;
    B.show();
    Arr C;
    //此处的=才是赋值运算符,默认的赋值=运算符调用的浅拷贝
    C = A;
    C.show();
    return 0;
}

前提2:类中有指针成员必须重载=运算符

 默认拷贝函数会出现断点错误

#include <iostream>
#include <string.h>
using namespace std;
class Name{
public:
    char* name;
public:
    Name(){
        name = NULL;
        cout << "WC_GZ" << endl;
    }
    Name(char* name){
        this->name = new char(strlen(name)+1);
        cout << "YG_GZ" << endl;
    }
    ~Name(){
        cout << "XGHS" << endl;
    }
    void show(){
        cout << "name= " << name << endl;
    }
};
int main()
{
    Name A("ucy");
    A.show();
    //默认的拷贝构造函数,是浅拷贝
    Name B = A;
    B.show();
    Name C;
    //默认的赋值=运算符调用的浅拷贝
    C = A;
    C.show();
    return 0;
}

自定义拷贝构造函数避免断点错误 

#include <iostream>
#include <string.h>
using namespace std;
class Name{
public:
    char* name;
public:
    Name(){
        name = NULL;
        cout << "WC_GZ" << endl;
    }
    Name(char* name){
        this->name = new char[strlen(name)+1];
        cout << "YC_GZ" << endl;
    }
    Name(const Name &n){
        this->name = new char[strlen(n.name)+1];
        strcpy(this->name, n.name);
        cout << "KB_GZ" << endl;
    }
    ~Name(){
        cout << "XGHS" << endl;
    }
    void show(){
        cout << "name= " << name << endl;
    }
};
int main()
{
    Name A("ucy");
    A.show();
    //自定义的拷贝构造函数
    Name B = A;
    B.show();
    return 0;
}

重载赋值运算符=

#include <iostream>
#include <string.h>
using namespace std;
class Name{
public:
    char* name;
public:
    Name(){
        name = NULL;
        cout << "WC_GZ" << endl;
    }
    Name(char* name){
        this->name = new char[strlen(name)+1];
        cout << "YC_GZ" << endl;
    }
    Name(const Name &n){
        this->name = new char[strlen(n.name)+1];
        strcpy(this->name, n.name);
        cout << "KB_GZ" << endl;
    }
    ~Name(){
        cout << "XGHS" << endl;
    }

    void show(){
        cout << "name= " << name << endl;
    }
    Name& operator=(Name &n){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
        this->name = new char[strlen(n.name)+1];
        strcpy(this->name, n.name);
        return *this;
    }
};
int main()
{
    Name A("ucy");
    A.show();
    //自定义的拷贝构造函数
    Name B = A;
    B.show();

    Name C, D, E;
    //可迭代重载=运算符
    E = D = C = A;
    C.show();
    D.show();
    E.show();
    return 0;
}

等于和不等于运算符重载(==,!=)

#include <iostream>
#include <string.h>
using namespace std;
class Name{
public:
    char* name;
public:
    Name(){
        this->name = NULL;
    }
    Name(char* name){
        this->name = new char[strlen(name)+1];
        strcpy(this->name, name);
    }
    ~Name(){
        if(this->name != NULL){
            delete [] this->name;
            this->name = NULL;
        }
    }
    bool operator==(Name &n){
        if(strcmp(this->name, n.name) == 0){
            return true;
        }
        if(strcmp(this->name, n.name) != 0){
            return false;
        }
    }
    bool operator!=(Name &n){
        if(strcmp(this->name, n.name) != 0){
            return true;
        }
        if(strcmp(this->name, n.name) == 0){
            return false;
        }
    }
};

int main()
{
    Name A("lucy");
    Name B("lucy");
    Name C("rex");
    if(A==B){
        cout << "A==B" << endl;
    }
    if(A!=B){
        cout << "A!=B" << endl;
    }
    if(A==C){
        cout << "A==C" << endl;
    }
    if(A!=C){
        cout << "A!=C" << endl;
    }
    return 0;
}

函数调用符()的重载(仿函数)

#include <iostream>

using namespace std;
class F{
public:
    int add(int x, int y){
        return x+y;
    }
    //重载(),第一个()是重载的符号,第二个()为了传参
    int operator()(int x, int y){
        return x+y;
    }
};

int main()
{
    F f;
    cout << f.add(1, 2) << endl;
    //重载()
    cout << f.operator()(1, 2) << endl;
    //简化 f和()结合,会自动寻找()运算符
    //此处f(1, 2)不是一个真正的函数,仅仅是对象名和()结合,调用()重载运算符而已
    //f不是函数名 只是f(1, 2)类似于函数调用,所以将f(1, 2)称为仿函数
    cout << f(1, 2) << endl;
    //F是类名称
    //F()是匿名对象
    cout << F()(1, 2) << endl;
    return 0;
}

 

 

期望结果为假,但实际结果为真 

强化训练 字符串类 (重要) 

字符串类包含字符串与字符串的操作

main.cpp

#include <iostream>
#include <mystring.h>

using namespace std;

int main()
{
    Mystring A("lucy");
    //重载<<
    cout << A;

    //重载>>
//    Mystring B;
//    cin >> A;
//    cin >> B;
//    cout << B << A;

    //重载[]
    cout << A[3] << endl;
    A[2] = 'b';
    cout<<A;

    return 0;
}

mystring.cpp

#include "mystring.h"
#include <iostream>
#include <string.h>
using namespace std;

Mystring::Mystring(){
    this->s = NULL;
    this->size = 0;
}

Mystring::Mystring(const char* s){
    this->s = new char[strlen(s)+1];
    strcpy(this->s, s);
    this->size = strlen(this->s);
}

Mystring::Mystring(const Mystring &s){
    if(this->s != NULL){
        delete [] this->s;
        this->s = NULL;
    }
    this->s = new char[s.size+1];
    strcpy(this->s, s.s);
    this->size = s.size;
}

Mystring::~Mystring(){
    if(this->s != NULL){
        delete [] this->s;
        this->s = NULL;
    }
}

//重载[]
char &Mystring::operator[](int index){
    if(index < 0 || index > this->size){
        cout << "out of space" << endl;
    }
    else{
        return this->s[index-1];
    }
}

//void Mystring::operator=(char n){

//}

//重载<<
ostream& operator<<(ostream &out, Mystring &T){
    out << "Str: " << T.s << ", Size: " << T.size << endl;
    return out;
}

//重载>>
istream& operator>>(istream &in, Mystring &T){
    if(T.s != NULL){
        delete [] T.s;
        T.s = NULL;
    }
    char d[1024] = "";
    in >> d;
    T.size = strlen(d);
    T.s = new char[T.size+1];
    strcpy(T.s, d);
    return in;
}

mystring.h

#ifndef MYSTRING_H
#define MYSTRING_H

#include <iostream>
using namespace std;
class Mystring
{
    friend ostream& operator<<(ostream &out, Mystring &T);
    friend istream& operator>>(istream &in, Mystring &T);
private:
    char* s;
    int size;
public:
    Mystring();
    Mystring(const char* s);
    Mystring(const Mystring &s);
    ~Mystring();

    char &operator[](int index);
//    void operator=(char n);
};

#endif // MYSTRING_H

注:仅用于学习总结

QT学习C++(11)_爱吃糖葫芦的大熊的博客-CSDN博客

QT学习C++(13)_爱吃糖葫芦的大熊的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值