最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

c++重載運(yùn)算符時(shí)返回值為類(lèi)的對(duì)象或者返回對(duì)象的引用問(wèn)題

 更新時(shí)間:2022年11月25日 10:02:08   作者:Jegret  
這篇文章主要介紹了c++重載運(yùn)算符時(shí)返回值為類(lèi)的對(duì)象或者返回對(duì)象的引用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

重載運(yùn)算符時(shí)返回值為類(lèi)的對(duì)象或者返回對(duì)象的引用

最終的目的是為了進(jìn)行連續(xù)的運(yùn)算

a = b + c + d; //不只是兩個(gè)對(duì)象相加,是為了兩個(gè)以上的對(duì)象的相加

以上面的代碼為例,假設(shè)a,b,c,d都是同一個(gè)類(lèi)(classA)的不同對(duì)象,假如我重載這個(gè)類(lèi)的加號(hào)時(shí),返回值類(lèi)型不是此類(lèi)或者他的引用,如下

void operator+(classA &a, classA &b)
{
?? ?//加法運(yùn)算
}

那么在我最上面的代碼中,b + c 的值就為空(或者其他類(lèi)型),那么這個(gè)得出來(lái)的值就沒(méi)有辦法繼續(xù)和d來(lái)進(jìn)行加法的運(yùn)算,也沒(méi)有辦法賦值給a了,這也就無(wú)法實(shí)現(xiàn)我所期望的連續(xù)運(yùn)算的目的。

所以,c++重載運(yùn)算符時(shí)返回值為類(lèi)的對(duì)象是為了實(shí)現(xiàn)連續(xù)的運(yùn)算(大多數(shù)這種運(yùn)算其實(shí)是賦值運(yùn)算或者<< >>)

如果你以后要重載運(yùn)算符,有什么連續(xù)運(yùn)算的需要,就可以使用這種方法,不過(guò)最好也要遵守c++中一些語(yǔ)法的規(guī)定,不要重載出來(lái)的東西讓人摸不著頭腦

那么,現(xiàn)在講為什么有一些函數(shù)要返回對(duì)象的引用,這其實(shí)是為了提高程序的運(yùn)行效率,眾所周知,當(dāng)一個(gè)函數(shù)返回一個(gè)值時(shí),他并不是將你在此函數(shù)里面原有的你想要的那個(gè)值返回,而是將你想要的那個(gè)值,復(fù)制一下,然后把這個(gè)復(fù)制出來(lái)的值給返回,如下

classA operator+(classA &a, classA &b)
{
?? ?classA temp;
?? ?//加法運(yùn)算
?? ?return temp;
}

代碼最終返回的并不是你在函數(shù)里定義的那個(gè)temp,而是將temp復(fù)制了一份,將復(fù)制的那份返回了,函數(shù)里定義的那個(gè)temp在函數(shù)運(yùn)行結(jié)束后就釋放了。

同理,就算你沒(méi)有在函數(shù)里面新建東西,而是直接返回通過(guò)a和b運(yùn)算出來(lái)的一些東西(或者你直接返回*this),他也要復(fù)制一下。

所以,只要你不采用返回類(lèi)的對(duì)象,而是返回類(lèi)的對(duì)象的引用,就不會(huì)復(fù)制,也即不會(huì)調(diào)用類(lèi)的復(fù)制構(gòu)造函數(shù),也即提升了程序的效率

classA & operator+(classA &a, classA &b)
{
?? ?//加法運(yùn)算
?? ?//a.time = a.time + b.time; //假設(shè)time是此類(lèi)的一個(gè)屬性
?? ?//return a;
?? ?//加法只有這樣可以實(shí)現(xiàn)連續(xù)的運(yùn)算,有些雞肋,但是=,<<,>>,就很好用了
}

所以,當(dāng)你重載的運(yùn)算符需要連續(xù)的運(yùn)算時(shí),你可以返回他的類(lèi)的對(duì)象。如果你想要減少不必要的開(kāi)銷(xiāo)(復(fù)制構(gòu)造函數(shù)),提高程序效率,并且你返回的對(duì)象是需要作為左值的話(huà),那么你可以返回他的引用

不過(guò)絕大部分 返回對(duì)象 或者 他的引用 實(shí)現(xiàn)連續(xù)運(yùn)算,都是用在重載 賦值運(yùn)算符= 或者 插入運(yùn)算符<< 或者 提取運(yùn)算符>> 中的。

那里面比較好用,其他的如加法那些,連續(xù)運(yùn)算就很雞肋,也比較難實(shí)現(xiàn),但是返回引用可以提升效率卻是真真的好啊

關(guān)于運(yùn)算符重載中返回值的坑及解決

相信不少朋友在學(xué)習(xí)運(yùn)算符重載的時(shí)候,都會(huì)被參數(shù)返回值應(yīng)該是左值引用,還是右值引用,還是const常量所困擾。當(dāng)然我無(wú)法一一枚舉,這次先講一下返回值的坑 (沒(méi)錯(cuò)就是我親手寫(xiě)的bug)

E0334 “Myclass” 沒(méi)有適當(dāng)?shù)膹?fù)制構(gòu)造函數(shù)

其實(shí)這個(gè)問(wèn)題的根源是,沒(méi)有定義常量參數(shù)類(lèi)型的拷貝構(gòu)造函數(shù)所致

先來(lái)看看代碼

//頭文件head.h
class Myclass
{
private:
	int a;
public:
	Myclass(int b=0):a(b) {}		//構(gòu)造函數(shù)
	Myclass(Myclass& c);			//復(fù)制構(gòu)造函數(shù)
	~Myclass(){}					//析構(gòu)函數(shù)
	Myclass operator+(Myclass& d);	//重載+運(yùn)算符
	friend ostream& operator<<(ostream& os ,const Myclass& d);
									//重載<<運(yùn)算符
};
//以下是定義
Myclass::Myclass(Myclass& c)
{
	a = c.a;
}
Myclass Myclass::operator+(Myclass& d)
{
	return Myclass(d.a+a);			//?。〈颂巿?bào)錯(cuò)
}
ostream& operator<<(ostream& os,const Myclass& d)
{
	os << d.a << std::endl;
	return os;
}
//main.cpp
#include"head.h"
int main()
{
	Myclass a1(5);
	Myclass a2(12);
	Myclass sum = a1 + a2;		//??!此處報(bào)錯(cuò)
	std::cout << sum;
}

代碼在VS中,又出現(xiàn)了令人討厭的小紅線(xiàn),沒(méi)有適當(dāng)?shù)膹?fù)制構(gòu)造函數(shù),這就有疑問(wèn)了, 不是明明有個(gè)構(gòu)造函數(shù)Myclass(int b=0):a(b) {}嗎,參數(shù)是int很合適啊?

于是,我們定義一個(gè)臨時(shí)變量temp,再將它返回,此時(shí)會(huì)隱式調(diào)用拷貝構(gòu)造函數(shù)而后返回一個(gè)副本后原來(lái)的temp就die了,因此返回值不可以是引用。

下面是代碼

Myclass Myclass::operator+(Myclass& d)
{
	Myclass temp(d.a + a);
	return temp;
}

此時(shí)第一處報(bào)錯(cuò)消失了,但是第二處報(bào)錯(cuò)依然存在,而且仍為 “沒(méi)有適當(dāng)?shù)膹?fù)制構(gòu)造函數(shù)”,這就說(shuō)明了,我的入手方向應(yīng)該是拷貝構(gòu)造函數(shù)

經(jīng)過(guò)博主的調(diào)試,得知是因?yàn)?strong>函數(shù)的返回值是一個(gè)純右值,為了驗(yàn)證這個(gè)想法,使用了右值引用,來(lái)接收這個(gè)純右值(當(dāng)然,右值引用更多的是用在移動(dòng)構(gòu)造函數(shù)上,將 將亡值“偷”出來(lái))

#include"head.h"
int main()
{
	Myclass a1(5);
	Myclass a2(12);
	Myclass&& sum = a1 + a2;
}

果然,它不報(bào)錯(cuò)了

但是考慮到實(shí)用性,總不能讓用戶(hù)今后做個(gè)加法都要用右值引用接收吧,因此,我們要從源頭解決,即重載拷貝構(gòu)造函數(shù)。

值得思考的是,右值不就是被賦值的那個(gè)嗎,為什么用Myclass&& sum = a1 + a2;無(wú)法賦值呢?眾所周知,Myclass&& sum = a1 + a2;調(diào)用的是拷貝構(gòu)造函數(shù),類(lèi)不同于基本數(shù)據(jù)類(lèi)型,它要通過(guò)程序員來(lái)

設(shè)置一系列的功能,我們沒(méi)有設(shè)置接受,Myclass類(lèi)型的右值的功能,只定義了接受int類(lèi)型的右值的功能,這自然是不行的了。

因此,重載拷貝構(gòu)造函數(shù)

Myclass::Myclass(const Myclass& c)
{
	a = c.a;
}

此時(shí)就能運(yùn)行了

E0349 沒(méi)有與這些操作數(shù)匹配的 “<<” 運(yùn)算符

關(guān)于流運(yùn)算符為什么要寫(xiě)成$ostream& operator<<(ostream& os,const Myclass& d); 而非ostream& operator<<(ostream& os,Myclass& d);這個(gè)問(wèn)題,網(wǎng)上絕大部分的回答都是輸出沒(méi)必要修改值。

那么我們先定義后者

#head.h
#pragma once
#include<iostream>
using std::ostream;
class Myclass
{
private:
	int a;
public:
	Myclass(int b=0):a(b) {}
	Myclass(Myclass& c);
	Myclass(const Myclass& c);
	~Myclass(){}
	Myclass operator+(Myclass& d);
	friend ostream& operator<<(ostream& os ,Myclass& d);
};
Myclass::Myclass(const Myclass& c)
{
	a = c.a;
}
Myclass::Myclass(Myclass& c)
{
	a = c.a;
}
Myclass Myclass::operator+(Myclass& d)
{
	Myclass temp(d.a + a);
	return temp;
}
ostream& operator<<(ostream& os,Myclass& d)
{
	os << d.a << std::endl;
	return os;
}
#main.cpp
#include"head.h"
int main()
{
	Myclass a1(5);
	Myclass a2(12);
	Myclass&& sum = a1 + a2;		
	std::cout << a1 + a2;				//此處有討厭小紅線(xiàn)
}

不難發(fā)現(xiàn),討厭的小紅線(xiàn)又出來(lái)了。

我們可以想象一下這個(gè)過(guò)程,a1.operator+(a2),返回了個(gè)臨時(shí)變量,暫且假設(shè)它叫newguy,那么newguy為一個(gè)右值,又調(diào)用了函數(shù)os.<<(&d),傳參為&d=newguy,現(xiàn)在問(wèn)題來(lái)了,左值引用怎么能夠接受一個(gè)純右值呢? 而我們定義的重載的流運(yùn)算符接受的參數(shù)類(lèi)型為左值,我們并沒(méi)有給出從左值到右值強(qiáng)制類(lèi)型轉(zhuǎn)換的函數(shù),但是在上一部分,我們給出了從右值到左值的拷貝構(gòu)造函數(shù),因此,將流運(yùn)算符聲明為前者更好。

C3861 “function”: 找不到標(biāo)識(shí)符

這個(gè)問(wèn)題應(yīng)該是非常常見(jiàn)的,不習(xí)慣將函數(shù)(或是類(lèi))先聲明后定義而又喜歡讓函數(shù)(或是類(lèi))相互調(diào)用,但是在類(lèi)模板它比以上兩種更為隱蔽。

#include<iostream>
class A
{
	friend void show();			//“聲明”函數(shù)
	friend void show1();		//“聲明”函數(shù)
}; 
void show()						//定義
{
	show1();
}
void show1(){}					//定義
int main()
{
	A a;
	show();						//調(diào)用
	show1();					//調(diào)用
}

以上流程看似聲明->定義->調(diào)用非常完美,實(shí)則還是會(huì)報(bào)錯(cuò)的,不過(guò)跟以上兩種不一樣的是,它是在linking的時(shí)候出錯(cuò),這是為什么呢?

原來(lái)友元函數(shù)并不屬于這個(gè)類(lèi)的一部分,在類(lèi)內(nèi)定義僅僅是為了告訴編譯器“這個(gè)函數(shù)是這個(gè)類(lèi)的友元函數(shù)”,并沒(méi)有對(duì)這個(gè)函數(shù)本身進(jìn)行聲明,因此,正確的做法應(yīng)該是這樣的:

#include<iostream>
void show();
void show1();
class A
{
	friend void show();
	friend void show1();
}; 
void show()
{
	show1();
}
void show1(){}
int main()
{
	A a;
	show();
	show1();
}

Summary

本文主要講了三點(diǎn)。

首先,要注意將拷貝構(gòu)造函數(shù)重載。

其次,要將流運(yùn)算符<<的參數(shù)類(lèi)型確定為(ostream&,const myclass&),當(dāng)然,istream則萬(wàn)萬(wàn)不可const,ostream是沒(méi)有拷貝構(gòu)造函數(shù)的,因此引用也是必須的。

最后,類(lèi)內(nèi)友元函數(shù)的聲明,并不等同于函數(shù)本身的聲明。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Socket通信原理和實(shí)踐

    Socket通信原理和實(shí)踐

    本文詳細(xì)講解了Socket通信原理和實(shí)踐,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • c++如何使用openssl接口來(lái)生成隨機(jī)數(shù)

    c++如何使用openssl接口來(lái)生成隨機(jī)數(shù)

    OpenSSL是一個(gè)強(qiáng)大的加密庫(kù),不僅支持加密解密,還能生成隨機(jī)數(shù),設(shè)置過(guò)程包括下載資源文件、配置項(xiàng)目及修改屬性頁(yè)等步驟,確保庫(kù)文件正確包含,在Visual Studio中正確配置后,可使用RAND_bytes函數(shù)生成隨機(jī)數(shù),此過(guò)程需要注意文件路徑和附加目錄的設(shè)置
    2024-10-10
  • 基于opencv的行人檢測(cè)(支持圖片視頻)

    基于opencv的行人檢測(cè)(支持圖片視頻)

    本文主要介紹了基于opencv的行人檢測(cè)(支持圖片視頻),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • C++ 中placement new 操作符使用方法

    C++ 中placement new 操作符使用方法

    這篇文章主要介紹了C++ 中placement new 操作符使用方法的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++中用兩個(gè)標(biāo)準(zhǔn)容器stack,實(shí)現(xiàn)一個(gè)隊(duì)列的方法詳解

    C++中用兩個(gè)標(biāo)準(zhǔn)容器stack,實(shí)現(xiàn)一個(gè)隊(duì)列的方法詳解

    本篇文章是對(duì)C++中使用兩個(gè)標(biāo)準(zhǔn)容器stack,實(shí)現(xiàn)一個(gè)隊(duì)列的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • QT利用QPainter繪制三維餅狀圖

    QT利用QPainter繪制三維餅狀圖

    這篇文章主要為大家詳細(xì)介紹了如何利用QPainter實(shí)現(xiàn)三維餅狀圖的繪制,由于Qt中沒(méi)有三維餅狀圖的繪制組件,因此只能自行繪制,感興趣的可以動(dòng)手嘗試一下
    2022-06-06
  • 常用C/C++預(yù)處理指令詳解

    常用C/C++預(yù)處理指令詳解

    預(yù)處理指令提供按條件跳過(guò)源文件中的節(jié)、報(bào)告錯(cuò)誤和警告條件,以及描繪源代碼的不同區(qū)域的能力。使用術(shù)語(yǔ)“預(yù)處理指令”只是為了與 C 和 C++ 編程語(yǔ)言保持一致。在 C# 中沒(méi)有單獨(dú)的預(yù)處理步驟;預(yù)處理指令按詞法分析階段的一部分處理。
    2014-11-11
  • C++開(kāi)放封閉原則示例解析

    C++開(kāi)放封閉原則示例解析

    在如那就的設(shè)計(jì)模式中,不能修改,但可以擴(kuò)展的實(shí)現(xiàn)是一條十分重要的原則,它是開(kāi)放-封閉原則(The Open-Clossed Principle,簡(jiǎn)稱(chēng)OCP)或開(kāi)-關(guān)閉原則
    2023-02-02
  • 基于OpenGL實(shí)現(xiàn)多段Bezier曲線(xiàn)拼接

    基于OpenGL實(shí)現(xiàn)多段Bezier曲線(xiàn)拼接

    這篇文章主要為大家詳細(xì)介紹了基于OpenGL實(shí)現(xiàn)多段Bezier曲線(xiàn)拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C++實(shí)現(xiàn)圖書(shū)管理系統(tǒng)源碼

    C++實(shí)現(xiàn)圖書(shū)管理系統(tǒng)源碼

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)圖書(shū)管理系統(tǒng)源碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評(píng)論

乌拉特前旗| 苏尼特右旗| 淄博市| 南岸区| 新田县| 吉安县| 怀宁县| 象山县| 昌平区| 阿坝县| 高邮市| 阜南县| 三穗县| 舒兰市| 和顺县| 蓬安县| 峨边| 荥阳市| 宝应县| 龙川县| 大名县| 青冈县| 青浦区| 辛集市| 平泉县| 隆昌县| 新源县| 博客| 皋兰县| 西吉县| 会泽县| 德格县| 濮阳县| 东光县| 抚州市| 绥滨县| 博罗县| 治县。| 宝坻区| 岢岚县| 高要市|