C++ 学习(3) ---- 运算符重载和赋值构造

2023-02-26  本文已影响0人  特立独行的佩奇

C++ 运算符重载

运算符重载的本质还是函数重载,可以将运算符理解为特殊的函数名:

箭头运算符->、下标运算符[ ]、函数调用运算符( )、赋值运算符= 只能以成员函数的形式重载

不可重载的运算符.jpg

可以重载的运算符基本可以分为:


可以重载的运算符.jpg
赋值运算符重载

只能以成员函数的形式重载,基本形式为:基本形式为 classname& operator=(classname& 实例对象)
注意输入参数只有一个,而且必须是对象的引用,返回值也必须是对象的引用
tips:可以将operator= 看成一个整体,当成函数名,赋值运算符重载函数也可以重载,即可以有多个

//声明
allOperatorDemo& operator=(allOperatorDemo& p);
allOperatorDemo& operator=(string str);

//定义
allOperatorDemo& allOperatorDemo::operator=(allOperatorDemo& p) {
    mstr = p.mstr;
    return *this;
}

allOperatorDemo& allOperatorDemo::operator=(string str) {
    mstr = str;
    mstr.append("=string_str");
    return *this;
}

//使用
// 赋值运算符重载
{
    allOperatorDemo p("init");
    p = "hello";
    cout << "p mstr: " << p.mstr << endl; // hello=string_str 

    allOperatorDemo q("demo");
    p = q;

    cout << "p mstr: " << p.mstr << endl; // demo
}
算术运算符重载

算术运算符包括+、++、–、- -、+=、-=、/、*等,作为成员函数重载的基本形式为:
classname& operator运算符(classname& 实例对象)
除了自增和自减运算符,其余算术运算符都是一个参数,返回值是对象的引用

tips: 运算符重载的参数可以任意定义,但是不能改变参数的个数

//声明
allOperatorDemo& operator+(allOperatorDemo& p);
allOperatorDemo& operator+(const char* str);
allOperatorDemo& operator-(allOperatorDemo& p);
allOperatorDemo& operator*(allOperatorDemo& p);
allOperatorDemo& operator/(allOperatorDemo& p);

allOperatorDemo& operator+=(allOperatorDemo& p);
allOperatorDemo& operator-=(allOperatorDemo& p);
allOperatorDemo& operator*=(allOperatorDemo& p);
allOperatorDemo& operator/=(allOperatorDemo& p);

//定义
allOperatorDemo& allOperatorDemo::operator+(allOperatorDemo& p) {
    mstr.append(p.mstr);
    return *this;
}

allOperatorDemo& allOperatorDemo::operator+(const char* str) {
    mstr.append(str).append("operator+_const_str");
    return *this;
}

allOperatorDemo& allOperatorDemo::operator-(allOperatorDemo& p) {
    mstr.append("operator-");
    return *this;
}

allOperatorDemo& allOperatorDemo::operator*(allOperatorDemo& p) {
    mstr.append("operator*");
    return *this;
}

.... //其余形式相同

注意算术运算符+,-,*,/ 的两种调用形式的区别

allOperatorDemo democ = demoa + demob  和

allOperatorDemo democ;
democ = demoa + demob;

第一种只会调用到 + 运算符重载,第二种先实例化了对象,会同时调用到赋值运算符和 + 运算符重载

调用形式如下:

// 算术运算符重载
{
    allOperatorDemo p("init");
    allOperatorDemo m("demo");

    //allOperatorDemo q = p + "hello";
    allOperatorDemo q = p + m;
    cout << "p mstr: " << p.mstr << endl; //p mstr: initdemo

}

{
    allOperatorDemo p("init");
    allOperatorDemo m("m");
    p += m;
    cout << "p mstr: " << p.mstr << endl; // p mstr: initoperator+=
}

+,-,*,/ 重载函数调用完成之后,两个输入对象作为参数,本身没有发生变化

注意使用 +=,-= 等也属于赋值运算符,只能定义为成员函数

关系运算符重载
bool operator>(allOperatorDemo& p);
bool operator>(const char* str);
bool operator>=(allOperatorDemo& p);
bool operator<(allOperatorDemo& p);
bool operator<=(allOperatorDemo& p);
bool operator==(allOperatorDemo& p);
bool operator!=(allOperatorDemo& p);

bool allOperatorDemo::operator>(allOperatorDemo& p) {
    return (mstr > p.mstr ? true : false);
}

bool allOperatorDemo::operator>(const char* str) {
return (mstr > str ? true : false);
}


bool allOperatorDemo::operator>=(allOperatorDemo& p) {
return (mstr >= p.mstr ? true : false);
}

关系运算符重载函数也是可以重载的,比如上面对 > 运算符的重载
调用形式:

// 关系运算符重载
{
    allOperatorDemo p("init");
    allOperatorDemo m("thismorning");

    cout << "p(init) > m(this morning) " << (p > m) << endl;
    cout << "p(init) >= m(this morning) " << (p >= m) << endl;
    cout << "p(init) < m(this morning) " << (p < m) << endl;
    cout << "p(init) <= m(this morning) " << (p <= m) << endl;
    cout << "p(init) == m(this morning) " << (p == m) << endl;
    cout << "p(init) != m(this morning) " << (p != m) << endl;
}
自增自减运算符重载

对于 p++ 和 ++p 这两种形式都是可以重载的,operator++(int) 对应于 p++这种形式,:operator++()对应于++p 这种形式

allOperatorDemo& operator++();
allOperatorDemo& operator++(int);
allOperatorDemo& operator--();
allOperatorDemo& operator--(int);

allOperatorDemo& allOperatorDemo::operator++() {
mstr.append("operator++");
return *this;
}

allOperatorDemo& allOperatorDemo::operator++(int) {
mstr.append("operator++_int");
return *this;
}
数组下标[ ] 运算符重载

只能以成员函数的形式重载

char operator[](uint32_t pos);
void operator[](string str);

char allOperatorDemo::operator[](uint32_t pos) {
return mstr[pos];
}


void allOperatorDemo::operator[](string str) {
mstr.append("[]_string_str");
}

{
    allOperatorDemo p("init");
    char c = p[2];
    cout << "p[2]: " << c << endl; //p[2]: i

    p["hello"];
    cout << "p mstr: " << p.mstr << endl; //p mstr: init[]_string_str
}

赋值构造函数

赋值构造函数(Assignment Constructor)是一种特殊的构造函数,用于将一个已存在的对象的值赋给另一个对象;赋值构造函数通常用于实现对象的赋值语句
demoClass p;
demoClass q = p;

需要注意的是,赋值构造函数与拷贝构造函数不同,拷贝构造函数用于将一个对象的值复制到另一个对象中,而赋值构造函数用于将一个已存在的对象的值赋给另一个对象

赋值构造函数的原型与拷贝构造函数类似,但是它使用赋值运算符(=)来初始化一个对象,例如:

demoClass& operator=(const demoClass& obj)

如果一个类没有显式定义赋值构造函数,编译器会生成一个默认的赋值构造函数,但是这个默认的构造函数只是进行浅拷贝(也就是仅仅复制指针或者成员变量的值),这可能会导致对象之间的数据共享或者内存泄漏问题,因此在需要复制对象时,建议自行实现赋值构造函数

赋值构造函数和拷贝构造函数的区别:

  1. 拷贝构造函数是构造函数的一种,它没有返回值,在创建新对象的时候如果使用下面的形式定义对象,拷贝构造函数会被自动调用到
    newkeyWordDemo p(10);
    newkeyWordDemo q(p);

  2. 赋值构造函数是 = 操作符的一种重载实现,参数是一个常量引用,返回值是对象的引用
    newkeyWordDemo p(10);
    newkeyWordDemo q = p;

上一篇 下一篇

猜你喜欢

热点阅读