
一. 函式的原型以及函式創建的時機
C++中創建一個空類:
C++代碼
class Empty {};
默認會生成4個函式,其函式的原型如下:
C++代碼
public:
Empty() { ... }
Empty(const Empty& rhs) { ... }
~Empty() { ... }
Empty& operator=(const Empty& rhs) { ... }
說明:1) 這些函式只有在需要呼叫的時候,編譯器才會生成,2) 4個函式都是public的,
3) 4個函式都是inline的(即函式定義在類的定義中的函式),4) 如果你顯式的宣告了這些函式中的任何一個函式,那么編譯器將不再生成默認的函式,
比如,當遇到下列陳述句時,函式會被編譯器生成:
C++代碼
Empty e1; //默認建構式
//物件銷毀時,解構式
Empty e2(e1);//拷貝建構式
e2 = e1;//賦值運算子
另外,還存在兩種默認的函式:就是取地址運算子和取地址運算子的const版本,這兩個函式在《Effective C++》中沒有提及,
C++代碼
public:
Empty* operator&() { ... }
const Empty* operator&() const { ... }
這兩個函式是確實存在的,正如下面的代碼可以正常作業:
C++代碼
#include <stdio.h>
class Empty {
};
int main(int argc, char** argv)
{
Empty a;
const Empty *b = &a;
printf("%p\n", &a); //呼叫取地址運算子
printf("%p\n", b); //呼叫const取地址運算子
}
一個容易被忽略的問題:自定義的拷貝建構式不僅會覆寫默認的拷貝建構式,也會覆寫默認的建構式,下面的代碼是編譯不過的,用戶必須再顯式的定義一個無參的建構式,
C++代碼
class Empty
{
public:
Empty(const Empty& e) { } //拷貝建構式
};
int main(int argc, char** argv)
{
Empty a;
}
二. 賦值運算子存在的問題
賦值運算子函式的行為與拷貝建構式的行為基本是相同的,編譯器生成賦值運算子函式是有條件的,如果會產生無法完成的操作,編譯器將拒絕產生這一函式,
那么什么時候編譯器無法完成賦值這一行為呢?考慮如下情形(來源Effective C++):
C++代碼
template<class T>
class NameObject {
public:
NameObject(std::string& name,const T& value);
private:
std::string& nameValue;//參考成員變數
const T objectValue; //const成員變數
};
然后考慮下面的陳述句會發生什么事:
C++代碼
std::string newDog("abc");
std::string oldDog("xxx");
NameObject
NameObject
p = s;//將會發生什么?
賦值陳述句之前,p.nameValue指向newDog, s.nameValue指向oldDog,那么賦值之后呢?p.nameValue應該指向s.nameValue指向的物件嗎?但是C++有一條規定:參考不能改指向另外一個物件,
對于變數objectValue,C++規定:更改const成員是不合法的,
因此如果上面兩種情形中的任何一種發生了,C++編譯器給出的回應是:拒絕編譯這一行的賦值動作,如果你這么做了,C++編譯器會報錯,
如果你執意要進行賦值操作,那么可以自己定義一個賦值運算子多載函式,

另外如果你想更好的提升你的編程能力,學好C語言C++編程!彎道超車,快人一步!筆者這里或許可以幫到你~
分享(原始碼、專案實戰視頻、專案筆記,基礎入門教程)
歡迎轉行和學習編程的伙伴,利用更多的資料學習成長比自己琢磨更快哦!
編程學習書籍:

編程學習資料:

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/270543.html
標籤:C++
下一篇:C++面向物件學習筆記(二)
