iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0
自我挑戰組

Effective C++ 讀書筆記系列 第 9

[Day 9] Know what functions C++ silently writes and calls

  • 分享至 

  • xImage
  •  

前言

終於進入第二章了!
第一章是C++的一些基本概念,而第二章是關於 "Constructors, Destructors, and Assignment Operators" ,也是C++物件的不可或缺的角色─管理物件的生成、初始化、清理與賦值,也因為他們無所不在,更要注意它們的運用,以免造成的傷害也是影響廣大!

你不可不知的class背後運作

首先登場的就是:

Know that functions C++ silently writes and calls

當寫出一個class的時候,C++其實會默默幫你補充以下幾項:

  • default constructor: (如果沒有另外宣告的話)
  • copy constructor
  • copy assigment operator
  • destructor

而仰賴C++自動生成的這幾項,都會是 "public""inline" 的。
如同以下範例,當你寫了這樣...

class Empty();

其實效果就等同:

class Empty{
public:
    Empty() {...} // default constructor
    Empty(const Empty& rhs) {...} // copy constructor
    ~Empty() {...} // destructor
    Empty& operator=(const Empty &rhs) {...} // copy assignment operator
}

當用到這些function的時候他們就會被產生,那什麼時候會用到他們呢?

Empty e1; // default constructor; destructor
Empty e2(e1); // copy constructor
e2 = e1; // cp[y assigment operator operator

Constructor跟 destructor不必多說,就是把其中base classnon-static data members的自動初始化跟destruct做一做。其中可以注意一下,如果有自行宣告constructor,那default constructor就不會被產生!不用擔心自己定義好需要有參數的constructor之後,還可以不用參數直接產生對應物件(例如:

templage<typeName T>
class NamedObject{
public:
    NamedObject(const std::string& name, const T& value);
private:
    std::string nameValue;
    T objectValue;

那以下是行不通的!

NamedObject n1; // error!

)

另外,自動生成的destructor會是non-virtual的,除非!這個class是繼承自一個有把destructor宣告為virtual的base class
而copy constructor跟copy assignment operator則會複製source object的non-static data members到target object。例如上面這個物件

NamedObject<int> no1("Smallest Prime Number", 2);
NamedObject<int> no2(no1);

copy constructor會怎麼運作呢?首先nameValue因為是string,他有copy constructor,所以nameValue的部分就照string的copy constructor把no1的string copy過去;而後面的objectValue是int,他是built-in type,所以objectValue則是會複製no1.objectValue的bits過去。copy assignment operator也是同樣運作方式。不過!以下情形例外:產生的assignment 不合法。這是什麼意思呢?假設NamedObject變成這樣:

templage<typeName T>
class NamedObject{
public:
    NamedObject(std::string& name, const T& value); // no const now!
private:
    std::string& nameValue; // reference now!
    const T objectValue; // const now!

而當我們這樣使用:

std::string newDog("A");
std::string oldDog("B");

NamedObject<int> a(newDog, 2);
NamedObject<int> b(oldDog, 20);

a=b;

此時,anameValue應該是什麼呢?它是reference,C++不允許reference參考到別的物件;退一步來說,就算可以改,這樣其他參考到同一位置的物件,也要跟著變嗎?另外objectValue應該要變嗎?可是它是const...
而對於這種情形,C++就直接不給過。如果你的class裡面有reference member,你就需要自行定義copy assignment operator。除了reference type,const member也是比照辦理。

另外還有一種情形C++不會自動產生copy assignment operator─base class的copy assignment被宣告為private的derived class,因為C++自動產生的copy assignment operator需要可以handle base class的部分,但base class的copy assignment operator不給call,那就沒辦法了。

總結

貼心重點提醒:

Compilers may implicitly generate a class's "default constructor", "copy constructor", "copy assigment operator", and "destructor."

這條準則其實就是提醒一下C++會自動產生這四大金剛,以及各個不會產生的情形就行了。如果之後有什麼情況想要避免,就要注意一下要把它ban掉(通常是不用)。

補充

(皆取自參考資料)

  • virtual function: 在物件導向程式設計領域,C++、Object Pascal 等語言中有虛擬函數(英語:virtual function)或虛擬方法(英語:virtual method)的概念。這種函數或方法可以被子類繼承和覆蓋,通常使用動態分派實現。這一概念是物件導向程式設計中(執行時)多型的重要組成部分。簡言之,虛擬函數可以給出目標函數的定義,但該目標的具體指向在編譯期可能無法確定。

虛擬函數


上一篇
[Day 8] Make sure that objects are initialized before they're used (2)
下一篇
[Day 10] Explicitly disallow the use of compiler-generated functions you do not want
系列文
Effective C++ 讀書筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言