C 11中繼承建構函式和委派建構函式

2021-08-03 14:00:02 字數 3085 閱讀 9907

1、繼承建構函式

在c++繼承中,我們可能會遇到下面這個例子

class base

base(char c)

:m_c(c)

private:

int m_value;

char m_c;

};class derived :public base

//那麼如果我們在構造b的時候想要擁有a這樣的構造方法的話,就必須乙個乙個的透傳各個介面,那麼這是很麻煩的

derived(int va)

:base(va)

derived(char c)

:base(c)

};

上面過程是很麻煩的,但是呢c++11中推出了繼承建構函式,使用using來宣告繼承基類的建構函式,我們可以這樣寫

class base1

base1(char c)

:m_c(c)

private:

int m_value;

char m_c;

};class derived1 :public base1

;public:

//假設派生類只是新增了乙個普通的函式

void display()

//使用繼承建構函式

using base1::base1;

};

而且,更神奇的是,c++11標準繼承建構函式被設計為跟派生類中的各個類預設函式(預設構造,析構,拷貝構造等)一樣是隱式宣告的。那麼這就意味著如果乙個繼承建構函式不被相關**使用,編譯器就不會產生真正的函式**,這樣比透傳更加節省了空間。

但是有一點問題就是繼承建構函式只會初始化基類的成員變數,對於派生類的成員變數就無能為力了,這個時候我們的快速初始化

成員變數就派上用場了,假如上面的derived1,有乙個成員變數m_d

還有一點就是,基類的建構函式可能會有預設值,但是對於繼承建構函式來講,引數的預設值是不會被繼承的。所以我們在使用

有引數的預設值的建構函式的基類的時候就必須要小心,我們可以看到下面例子

class a

private:

int m_a;

double m_b;

};

那麼a中的建構函式會有下面幾個版本

a()a(int)

a(int,double)

a(consta&)

那麼b中對應的也就這幾個版本了

b()b(int)

b(int,double)

b(constb&)

有的時候在多繼承的情況下,還回出現衝突的情況,比如下面例子

class c

};class d

};class e :public c, public d

};

我們還要注意的一點就是私有構造是不會被繼承的

2、委派建構函式

c++11的委派建構函式是在建構函式的初始化列表位置進行構造的,委派的

假如我們也這樣乙個例子

class info

int type = 3;

char c = 'd';

public:

info()

info(int i)

:type(i)

info(char cc)

:c(cc)

};

這樣我們三個建構函式,都呼叫了init初始化,這樣很麻煩,我們可以利用委託建構函式改寫

class info1

int type = 3;

char c = 'd';

public:

info1()

info1(int i)

:info1()

info1(char cc)

:info1()

};

這樣的版本就比上面簡單多了

上面的init()函式被稱為目標建構函式

其它兩個建構函式被稱為委派建構函式

但是呢我們要注意的一點就是我們不能同時使用委派建構函式和初始化列表,例如下面的例子就是錯的

info1(int i)

:info1(),type(i)

但是上面的**卻會出現乙個錯誤的例子,比如我們在init中出現這樣的一行**:type = type + 1;

那麼我們呼叫info1 f(3);

那麼過去我們會先進行委派建構函式,因為就地初始化比列表初始化都快,那麼肯定的是type先被就地初始化為3,然後執行3+1等於4

最後執行type = i;將type重新賦值3

那麼我們可以看到就地初始化出問題了,那麼我們可以在類裡面加乙個通用的私有的建構函式,我們可以這樣寫

class info2

public:

info2()

:info2(1, 'a')

info2(int i)

:info2(i, 'a')

info2(char e)

:info2(1, e)

};

這樣就不會出錯了

而在建構函式比較多的時候,我們可能會擁有不止乙個委派建構函式,有的函式可能既是目標建構函式,又是委派建構函式的就會出現鏈式結構,但是我們卻不能出現環式結構,環式結構會出現錯誤

委派構造還有乙個很實用的應用就是使用構造模板函式產生目標建構函式

我們可以看到下面的例子

class tdconstructed

listl;

public:

tdconstructed(vector& v)

:tdconstructed(v.begin(), v.end())

tdconstructed(deque& d)

:tdconstructed(d.begin(), d.end())

};

此外在處理異常方面,如果在委派建構函式中使用try的話,那麼從目標建構函式產生的異常,都可以在委派建構函式中**捉到

C 11 委派建構函式

一 委派建構函式 深入理解c 11 委派構造 就是指委派函式將構造的任務派給了目標建構函式來完成這樣一種類構造的方式。c 11中的委派建構函式是在建構函式的初始化列表位置進行構造的 委派的 基準版本 的建構函式稱為目標建構函式,呼叫 基準版本 的建構函式稱為委派建構函式 舉例 namespace d...

C 11初窺二 繼承建構函式和委派建構函式

分析了這兩種用法,真想吐槽兩句,這兩個特性確實有實際需要,但客觀來說,現有標準足夠用,而且帶來的代價也非常大,又給c 複雜的語法糖重重的抹了一筆!一 繼承建構函式 繼承建構函式的引入原因 如果基類的建構函式很多,那麼子類的建構函式想要實現同樣多的構造介面,必須一一呼叫基類的建構函式,有點麻煩 於是乎...

C 繼承建構函式和委派建構函式

如果我們在構造b的時候想要擁有a這樣的構造方法的話,就必須乙個乙個的透傳各個介面,那麼這是很麻煩的derived int va base va derived char c base c 改寫成這樣 使用繼承建構函式 using base1 base1 而且,更神奇的是,c 11標準繼承建構函式被設...