C++运算符重载(四)之赋值运算符重载

简介: 赋值运算符重载c++编译器至少给一个类添加4个函数1. 默认构造函数(无参,函数体为空)2. 默认析构函数(无参,函数体为空)3. 默认拷贝构造函数,对属性进行值拷贝4. 赋值运算符 operator=, 对属性进行值拷贝如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题示例:


赋值运算符重载

c++编译器至少给一个类添加4个函数

  1. 默认构造函数(无参,函数体为空)
  2. 默认析构函数(无参,函数体为空)
  3. 默认拷贝构造函数,对属性进行值拷贝
  4. 赋值运算符 operator=, 对属性进行值拷贝

如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

示例:

classPerson

{

public:

   Person(intage)

   {

       //将年龄数据开辟到堆区

       m_Age=newint(age);

   }

   //重载赋值运算符

   Person&operator=(Person&p)//注意是引用

   {

       if (m_Age!=NULL)

       {

           deletem_Age;

           m_Age=NULL;

       }

       //编译器提供的代码是浅拷贝,赋值时只会将指针所指向的的地址进行赋值,释放堆区的数据时会造成浅拷贝问题。

       //m_Age = p.m_Age;

       //提供深拷贝 解决浅拷贝的问题

       m_Age=newint(*p.m_Age);//重新开辟一块堆区,各自释放各自的堆区。

       //返回自身

       return*this;//是为了实现连续赋值操作

   }

   ~Person()

   {

       if (m_Age!=NULL)

       {

           deletem_Age;

           m_Age=NULL;//如果指针不为空就释放指针指向的堆区内存,并且让指针的指向改为NULL,防止之后误操作。

       }

   }

   //年龄的指针

   int*m_Age;

};

voidtest01()

{

   Personp1(18);

   Personp2(20);

   Personp3(30);

   p3=p2=p1; //连续赋值操作

   cout<<"p1的年龄为:"<<*p1.m_Age<<endl;

   cout<<"p2的年龄为:"<<*p2.m_Age<<endl;

   cout<<"p3的年龄为:"<<*p3.m_Age<<endl;

}

intmain() {

   test01();

   //int a = 10;

   //int b = 20;

   //int c = 30;

   //c = b = a;//连续赋值操作,前提是a,b,c 的数据类型是相同的。

   //cout << "a = " << a << endl;

   //cout << "b = " << b << endl;

   //cout << "c = " << c << endl;

   system("pause");

   return0;

}

如果指针不为空就释放指针指向的堆区内存,并且让指针的指向改为NULL,防止之后误操作。

实例

一、定义一个日期类用于测试

classDate

{

public:

   Date(intyear=1900, intmonth=1, intday=1):_year(year),_month(month),_day(day)

   {}

   voidprint()//输出日期

   {

       cout<<_year<<"/"<<_month<<"/"<<_day<<endl;

   }

private:

   int_year;

   int_month;

   int_day;

};

正常情况下如果想比较两个日期大小是无法实现的,这是因为运算符默认都是给内置类型用的。

intmain()

{

   Dated1(2022, 2, 21);

   Dated2(2022, 2, 23);

   Dated3(2022, 2, 24);

   //d1 == d2;直接比较会导致无法编译

   return0;

}

二、重载运算符==函数名:operator加上运算符参数:有几个操作数就有几个参数,参数类型就是要操作对象的类型返回值:看运算符运算后的返回值是什么

//存在this指针,要少传一个参数

   booloperator==(constDate&x)//引用节省空间,const保护实参

   {

       return_year==x._year&&_month==x._month&&_day==x._day;

   }

公有函数无法访问私有变量,所以运算符重载要写在类内当作成员函数c

三、日期赋值=参数类型返回值检测是否自己给自己赋值返回 * this一个类如果没有显式定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝。如果不写,会默认生成赋值重载,和拷贝构造行为类似,内置类型会完成值拷贝,自定义类型成员会调用他的赋值重载

//赋值重载

   Dateoperator=(constDate&d)//返回值类型是Date

   {

       _year=d._year;

       _month=d._month;

       _day=d._day;

       return*this;//支持连续赋值,this是当前对象的别名,拷贝构造。

   }

测试结果

intmain()

{

   Dated1(2022, 2, 21);

   Dated2(2022, 2, 23);

   Dated3(2022, 2, 24);

   d1==d2;

   //d1.operator== (d2);//可以调用但可读性差

   //d1 == d2;//编译器自动转换为 d1.operator== (d2);  

 

   d1=d3;

   d1.print();

   //赋值运算符重载:用于两个已经定义出的对象间的拷贝赋值

   

   //拷贝构造:一个对象准备定义时,用另一个对象来初始化他

   Dated4(d3);

   d4.print();

   Dated5=d3;//这里是拷贝构造,只要是创建时定义就是拷贝构造,注意区分赋值重载。

   d1=d3=d2;//连续赋值,链式编程思想

   d1.print();

   return0;

}

注意

不能通过连接其他符号来创建新的操作符:比如operator@重载操作符必须有一个类类型或者枚举类型的操作数用于内置类型的操作符,其含义不能改变,例如:内置的整型 + ,不 能改变其含义作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参.*、::、sizeof 、 ? : 、.注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

总结

栈:构造,析构,拷贝构造,赋值重载都需要自己写日期类除构造函数外都可以使用编译器默认

目录
相关文章
|
3月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
150 5
|
5月前
|
C++
C++(十五) 运算符重载
C++中的运算符重载允许对已有运算符的功能进行重新定义,从而扩展语言功能、简化代码并提升效率。重载遵循特定语法,如 `friend 类名 operator 运算符(参数)`。重载时需注意不可新增或改变运算符数量、语义、优先级、结合性和返回类型。常见示例包括双目运算符 `+=` 和单目运算符 `-` 及 `++`。输入输出流运算符 `&lt;&lt;` 和 `&gt;&gt;` 也可重载。部分运算符只能作为成员函数重载。
|
7月前
|
自然语言处理 程序员 C++
C++基础知识(五:运算符重载)
运算符重载是C++中的一项强大特性,它允许程序员为自定义类型(如类或结构体)重新定义标准运算符的行为,使得这些运算符能够适用于自定义类型的操作。这样做可以增强代码的可读性和表达力,使得代码更接近自然语言,同时保持了面向对象编程的封装性。
|
7月前
|
Java 程序员 C++
|
7月前
|
编译器 C++
【C++】详解运算符重载,赋值运算符重载,++运算符重载
【C++】详解运算符重载,赋值运算符重载,++运算符重载
|
8月前
|
编译器 C++
【C++】类和对象③(类的默认成员函数:赋值运算符重载)
在C++中,运算符重载允许为用户定义的类型扩展运算符功能,但不能创建新运算符如`operator@`。重载的运算符必须至少有一个类类型参数,且不能改变内置类型运算符的含义。`.*::sizeof?`不可重载。赋值运算符`=`通常作为成员函数重载,确保封装性,如`Date`类的`operator==`。赋值运算符应返回引用并检查自我赋值。当未显式重载时,编译器提供默认实现,但这可能不足以处理资源管理。拷贝构造和赋值运算符在对象复制中有不同用途,需根据类需求定制实现。正确实现它们对避免数据错误和内存问题至关重要。接下来将探讨更多操作符重载和默认成员函数。
|
30天前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
67 19
|
30天前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
46 13
|
30天前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
48 5
|
30天前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
38 5