c/c++赋值函数(重载=号运算符)
c/c++赋值函数(重载=号运算符)
首先c++里的各种运算符都是用函数实现的,比如=,就等号函数。
所以当用=给一个对象赋值的时候,实际调用的是=号所对应的=号函数。
分析下面的代码
#include <iostream>
using namespace std;
class Test{
public:
explicit Test(){
data = 0;
}
explicit Test(int d):data(d){
cout << "C:" << this << ":"<< this->data << endl;
}
//拷贝构造函数
Test(const Test &t){
cout << "Copy:" << this << endl;
data = t.data;
}
//重载=号运算符
Test& operator= (const Test &t){
cout << "assign" << this << endl;
if(this != &t){
data = t.data;
}
return *this;
}
~Test(){
cout << "F:" << this << ":" << this->data << endl;
}
private:
int data;
};
int main(){
Test t1(10);
Test t2, t3;
t3 = t2 = t1;
return 0;
}
重点分析下面的函数
//重载=号运算符
Test& operator = (const Test &t){
cout << "assign" << this << endl;
if(this != &t){
data = t.data;
}
return *this;
}
分析点:
1,operator =是什么意思
2,参数为什么是引用类型
3,参数为什么有const限制
4,为什么有if(this != &t)的判断
5,为什么有返回值
6,为什么返回值的类型是引用类型
分析点解答:
Test t2;
t2 = t1;//实际的运作方式是t2.operator=(t1),所以函数里面的this就是t2
1,重载类Test的=号函数,当对类Test的对象用=号操作的时候,就会调用这个重载后的函数
2,避免调用拷贝构造函数
3,避免不小心修改里参数t里面成员变量的值(t.data = 100;)
4,防止自己给自己赋值
5,为了能够使用 t3 = t2 = t1。如果没有返回值,则t3.operator=(t2=t1),的参数里面t2=t1就没有返回值,所以编译不过。
6,不是引用也可以,用引用类型是防止老版本的编译器,在return处调用拷贝构造函数,新版本的编译器(gcc 4.8.5-20),即使不用引用类型,就不会调用拷贝构造函数。
一个大大的疑问,求高人指点
下面代码,重载了=号函数,故意把fun函数的返回值类型设置为引用,t2 = fun(t1);的执行结果:t2的data还是0,符合常理。
#include <iostream>
using namespace std;
class Test{
public:
Test(int d = 0):data(d){
cout << "C:" << d << " " << this << endl;
}
Test(Test &t){
cout << "Copy:" << t.data << " " << this << endl;
data = t.data;
}
Test& operator = (const Test &t){
cout << "Assign:" << this << " = " << &t << endl;
if(this != &t){
data = t.data;
}
return *this;
}
~Test(){
cout << "F:" << this->data << "->" << this << endl;
}
int getData()const{
return data;
}
private:
int data;
};
Test& fun(Test &x){
int value = x.getData();
Test tmp(value);
return tmp;
}
int main(){
Test t1(100);
Test t2;
t2 = fun(t1);
cout << t2.getData() << endl;
//Test t2 = fun(t1);
return 0;
}
但是,注释掉重载的=号函数,故意把fun函数的返回值类型设置为引用,t2 = fun(t1);的执行结果:t2的data居然是100,不符合常理,求高人指点
#include <iostream>
using namespace std;
class Test{
public:
Test(int d = 0):data(d){
cout << "C:" << d << " " << this << endl;
}
Test(Test &t){
cout << "Copy:" << t.data << " " << this << endl;
data = t.data;
}
/*
Test& operator = (const Test &t){
cout << "Assign:" << this << " = " << &t << endl;
if(this != &t){
data = t.data;
}
return *this;
}
*/
~Test(){
cout << "F:" << this->data << "->" << this << endl;
}
int getData()const{
return data;
}
private:
int data;
};
Test& fun(Test &x){
int value = x.getData();
Test tmp(value);
return tmp;
}
int main(){
Test t1(100);
Test t2;
t2 = fun(t1);
cout << t2.getData() << endl;
//Test t2 = fun(t1);
return 0;
}
c/c++赋值函数(重载=号运算符)的更多相关文章
- C++ //多态 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 //动态多态:派生类和虚函数实现运行时多态
1 //多态 2 //静态多态:函数重载 和 运算符重载 属于静态多态 ,复用函数名 3 //动态多态:派生类和虚函数实现运行时多态 4 5 //静态多态和动态多态的区别 6 //静态多态的函数地址早 ...
- 深入理解c++构造函数, 复制构造函数和赋值函数重载(operator=)
注 以下代码编译及运行环境均为 Xcode 6.4, LLVM 6.1 with GNU++11 support, Mac OS X 10.10.2 调用时机 看例子 // // main.cpp / ...
- C++友元函数重载"++"和"--"运算符
代码: #include <iostream> #include <cstring> using namespace std; class one{ public: one(i ...
- C++ //运算符重载 +号
1 #include <iostream> 2 #include <string> 3 using namespace std; 4 5 //1.成员函数重载 +号 6 cla ...
- C++:成员运算符重载函数和友元运算符重载函数的比较
5.2.4 成员运算符重载函数和友元运算符重载函数的比较 (1)对双目运算符而言,成员运算符重载函数参数表中含有一个参数,而友元运算符重载函数参数表中有两个参数:对于单目运算符而言,成员运算符重载函数 ...
- C++:运算符重载函数之成员运算符重载函数
5.2.3 成员运算符重载函数 在C++中可以把运算符重载函数定义为某个类的成员函数,称之为成员运算符重载函数. 1. 定义成员运算符重载函数的语法形式 (1)在类的内部,定义成员运算符重载函数的格式 ...
- C++:运算符重载函数之友元运算符重载
5.2.2 友元运算符重载函数 运算符重载函数一般采用两种形式定义: 一是定义为它将要操作的类的成员函数(简称运算符重载函数): 二是定义为类的友元函数(简称为友元运算符重载函数). 1.定义友元运算 ...
- C++第五次作业--运算符重载和函数重载
C++ 运算符重载和函数重载 C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是 ...
- C++类中的一些细节(重载、重写、覆盖、隐藏,构造函数、析构函数、拷贝构造函数、赋值函数在继承时的一些问题)
1 函数的重载.重写(重定义).函数覆盖及隐藏 其实函数重载与函数重写.函数覆盖和函数隐藏不是一个层面上的概念.前者是同一个类内,或者同一个函数作用域内,同名不同参数列表的函数之间的关系.而后三者是基 ...
随机推荐
- 【原创】Python第一章
Python总是从第一行代码开始逐步执行,而C是从main函数开始执行. 在Python中,一切东西都是对象. 在Python中,没有C的花括号,不能任意排版,属于同一个语句块的语句需 ...
- koa2入门使用总结
koa2的介绍 Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小.更富有表现力.更健壮的基石. 通过利用 async ...
- SHELL脚本--变量(基础)
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 变量存在于内存中.假设变量str,设置或修改变量属性时,不带$ ...
- linux四剑客-grep/find/sed/awk/详解-技术流ken
四剑客简介 相信接触过linux的大家应该都学过或者听过四剑客,即sed,grep,find,awk,有人对其望而生畏,有人对其爱不释手.参数太多,变化形式太多,使用超级灵活,让一部分人难以适从继而望 ...
- 前端学习(一) —— HTML
1.js跳转 window.location.href='url'; 2.div显示与隐藏 hide() show() 3.判断是否为一个字符串是否为整形 function isInt(str){ v ...
- WPF里ItemsControl的分组实现 --listbox 实现分组
我们在用到ItemsControl时,有时会用到分组,如ListBox,ListView,DataGrid.WPF的ItemsControl可以实现分组,是依托于GroupStyle,以ListBox ...
- Android Studio 活动启动模式
启动模式一共分4种 可以再配置文件中设置 <activity android:name=".MainActivity" android:launchMode="si ...
- 26.C++- 泛型编程之类模板(详解)
在上章25.C++- 泛型编程之函数模板(详解) 学习了后,本章继续来学习类模板 类模板介绍 和函数模板一样,将泛型思想应用于类. 编译器对类模板处理方式和函数模板相同,都是进行2次编译 类模板通 ...
- 异常:android.os.NetworkOnMainThreadException
场景: 安卓开发时在主线程访问网络解决: 将访问网络的代码使用Thread操作 Handler handler = new Handler(){ @Override public void handl ...
- 如何在Promise链中共享变量?
译者按: 使用Promise写过异步代码的话,会发现在Promise链中共享变量是一个非常头疼的问题,这也是Async/Await胜过Promise的一点,我们在Async/Await替代Promis ...