赋值运算符(=)重载
在C++中,赋值运算符可以被重载,允许用户定义类对象的赋值行为。通过重载赋值运算符,可以自定义对象的赋值操作,以便适应特定的需求和语义。当我们定义一个自定义的类时,比如一个简单的 MyString
类,可以通过重载赋值运算符来实现对象之间的赋值操作。
这里我将赋值运算符的重载简单的分成两类:
1.简单数值赋值时的重载 2.字符串赋值时的重载
赋值运算符重载(数值):
首先熟悉以下我们的自定义类MyString
,MyString
类具有两个公共成员变量 m_nNumberA
和 m_nNumberB
,分别表示整数类型的数据。类中包括两个构造函数,一个默认构造函数和一个带有两个参数的构造函数。
class MyString {
public:
int m_nNumberA;
int m_nNumberB;
public:
MyString() {};
MyString(int NumberA, int NumberB) :m_nNumberA(NumberA), m_nNumberB(NumberB) {};
}
接着重载赋值运算符来实现该类的对象之间的赋值操作:当对象进行赋值时只需要对m_nNumberA
和m_nNumberB
进行赋值即可,代码如下;
MyString operator=(const MyString &obj)
{
this->m_nNumberA = obj.m_nNumberA;
this->m_nNumberB = obj.m_nNumberB;
return *this;
}
这个时候我们在程序中进行使用:
int main() {
MyString StringObjA(20,30);
MyString StringObjB;
StringObjB = StringObjA;
std::cout << StringObjB.m_nNumberA << std::endl;
std::cout << StringObjB.m_nNumberB << std::endl;
system("pause");
return 0;
}
在main函数中首先创建了两个 MyString
对象 StringObjA
和 StringObjB
,并初始化了 StringObjA
的成员变量为 (20, 30)
。然后,通过赋值操作 StringObjB = StringObjA;
,将 StringObjA
的值赋给了 StringObjB
。最后,打印了 StringObjB
的成员变量值。
运行结果:
注意:使用重载后的赋值运算符时不能将对象的声明与赋值运算符写在一行代码中,即不能在声明对象时初始化对象,如MyString StringObjB= StringObjA;
这样写编译器会默认去调用类的拷贝构造函数而不会调用重载后的赋值运算符。
接着我们在上述重载的基础上接着阐述在遇到字符串时赋值运算符如何进行重载:
赋值运算符重载(字符串):
定义了一个名为 MyString
的类,其中包含了三个公共成员变量:m_nNumberA
、m_nNumberB
和 szStr
。前两个成员变量是整型数据,用于存储整数值;第三个成员变量是字符指针,用于存储字符串。
类中包括了两个构造函数:一个是默认构造函数,另一个是带有三个参数的构造函数,用于初始化对象的成员变量。在带有三个参数的构造函数中,进行了字符串的深拷贝操作,即动态分配了内存来存储字符串,并将参数 szBuf
中的字符串内容复制到了新分配的内存中。
class MyString {
public:
int m_nNumberA;
int m_nNumberB;
char * szStr = nullptr;
public:
MyString() {};
MyString(int NumberA, int NumberB,char * szBuf) :m_nNumberA(NumberA), m_nNumberB(NumberB) {
//深拷贝
szStr = new char[strlen(szBuf) + 1];
memset(szStr,0, strlen(szBuf) + 1);
strcpy(szStr, szBuf);
};
MyString operator=(const MyString &obj){
//数值赋值
this->m_nNumberA = obj.m_nNumberA;
this->m_nNumberB = obj.m_nNumberB;
//字符串赋值(深拷贝)
this->szStr = new char[strlen(obj.szStr) + 1];
memset(szStr,0, strlen(obj.szStr) + 1);
strcpy(this->szStr, obj.szStr);
return *this;
}
接着,代码尝试重载了赋值运算符。在赋值运算符的重载函数中,首先进行了数值的赋值操作,即将右侧对象的整数成员变量值赋给了左侧对象的相应成员变量。然后进行了字符串的赋值操作,同样进行了深拷贝,以确保每个对象都拥有独立的字符串内存空间。
在程序中进行使用:
int main() {
char szString[] = "wolven";
MyString StringObjA(20,30, szString);
MyString StringObjB;
StringObjB = StringObjA;
std::cout << StringObjB.m_nNumberA << std::endl;
std::cout << StringObjB.m_nNumberB << std::endl;
std::cout << StringObjB.szStr << std::endl;
system("pause");
return 0;
}
在这段 main
函数中,我们首先声明了一个字符数组 szString
,其中存储了字符串 "wolven"
。然后,我们创建了两个 MyString
类的对象 StringObjA
和 StringObjB
。对于 StringObjA
,我们使用带有三个参数的构造函数进行初始化,分别传入整数值 20
和 30
,以及字符数组 szString
,这个构造函数会对传入的字符数组进行深拷贝。对于 StringObjB
,我们使用默认构造函数进行初始化。接着,我们将 StringObjA
的值赋给了 StringObjB
,这会调用赋值运算符重载函数,将 StringObjA
的成员变量值复制给 StringObjB
的相应成员变量,同时进行了字符串的深拷贝操作。
运行结果:
对象成功进行赋值
!!注意:使用重载后的赋值运算符时不能将对象的声明与赋值运算符写在一行代码中,即不能在声明对象时初始化对象,如MyString StringObjB= StringObjA;
这样写编译器会默认去调用类的拷贝构造函数而不会调用重载后的赋值运算符。
相等比较运算符(==)重载
在C++中,==
是,用于比较两个值是否相等。如果两个值相等,则表达式的结果为真(true),否则为假(false)。
示例:
定义一个名为 MyString
的类,其中包含两个整数成员变量 m_nNumberA
和 m_nNumberB
,以及一个指向字符数组的指针 szStr
。它重载了 ==
运算符,以便在对象之间进行相等性比较。
class MyString {
public:
int m_nNumberA;
int m_nNumberB;
char * szStr = nullptr;
MyString() {};
MyString(int NumberA, int NumberB,char * szBuf) :m_nNumberA(NumberA), m_nNumberB(NumberB) {
//深拷贝
szStr = new char[strlen(szBuf) + 1];
memset(szStr,0, strlen(szBuf) + 1);
strcpy(szStr, szBuf);
};
// == 类内重载
bool operator==(const MyString &obj){
if (!strcmp(this->szStr, obj.szStr)) {
if (this->m_nNumberA == obj.m_nNumberA && this->m_nNumberB == obj.m_nNumberB) {
return true;
}
}
return false;
}
};
在 operator==
函数中,首先使用 strcmp
函数比较两个对象的 szStr
指向的字符串是否相等。如果字符串相等,则进一步比较两个对象的整数成员变量 m_nNumberA
和 m_nNumberB
是否也相等。如果字符串和两个整数都相等,则返回 true
,否则返回 false
。
使用:
int main(){
MyString StringObjA(20,30, szString);
MyString StringObjB(20,30, szString);
if (StringObjA == StringObjB) {
std::cout << "SAME" << std::endl;
}
}
在 main
函数中,首先创建了两个 MyString
类的对象 StringObjA
和 StringObjB
,它们的成员变量都被初始化为相同的值。然后通过 ==
运算符将它们进行比较,如果相等则输出 "SAME"。