C++ Q&A(六)構造函數的常見問題

聲明:Q&A系列的文章是我在平時自己遇到的或者看到的一些問題,本着再小的問題也需要有人解答的想法,將這些問題和答案整理出來。

歡迎和我討論問題,同時也歡迎轉載Q&A系列的文章。


前兩篇文章說了new運算符的有些相關知識,現在我們再來探討一下有關C++的構造函數的問題。下面的問題都是在面試中很 經常被問到的。


1.構造函數可以是虛嗎?

我在面CVTE的二面的時候就被問了這個問題。首先先放上結論:不可以。原因有兩個:

a)虛函數也只是一個函數,調用虛函數的時候,我們需要的只是這個虛函數的接口信息就可以了。但是調用構造函數就需要這個類的完整信息,包括類的大小等等。是不是有點矛盾。你可能會說,那我有類的全部信息一樣可以調用虛函數啊?那請看第二個原因。

b)C++的虛機制是通過虛函數表實現的,擁有虛函數的類都有一個指向虛函數表的指針(vptr),而這個vptr是在構造期間被賦值的,那麼問題來了,如果類還沒構造起來起來,怎麼找到類的虛函數呢?明顯是不可以的。


2.虛函數可以有返回值嗎?

這個同樣也是CVTE的二面問題。結論:不可以。

用代碼來解釋一下吧。如果虛函數有返回值,就有這樣的歧義:

class A {
public :
    int A() { return 0; };
};
那麼下面一個語句構造的是什麼類型:

pa = new A();
那pa是什麼類型?int還是A的指針?這就存在歧義的。

往深入的層面說,構造函數是一個回調函數,沒有返回值的。


3.什麼時候需要複製構造函數?

這個在C++Primer中有說到,下面內容摘自C++ Primer第五版:

拷貝初始化不僅在我們使用=定義變量時會發生,在下列情況下也會發生:

1.將一個對象作爲實參傳遞給非引用類型的形參

2.從一個返回類型爲非引用類型的函數返回一個對象

3.用花括號列表初始化一個數組中的元素或一個聚合類中的成員


4.什麼時候需要將一個類的構造函數聲明爲explicit?

將一個類的構造函數聲明聲明爲explicit是爲了防止隱式轉換的發生。舉個例子:

<span style="font-size:10px;">#include <stdio.h>
#include <stdlib.h>
class A {
public :
  A(int i) { _i = i; }
  const A operator += (const A &rhs) {
    _i += rhs._i;
    return *this;
  }
  int i() const { return _i; }
private :
  int _i;
};
int main() {
  A a(10);
  printf("%d\n", a.i());
  a += 10;
  printf("%d\n", a.i());
  return 0;
}</span>
因爲A的構造函數沒有被聲明爲explicit,因此,int到A類型的隱式轉換就發生了。那麼什麼會發生因此其他類型到類類型的隱式轉換呢?

1.類似上面的例子,當類的構造函數只有一個單一參數的時候

2.當一個類的構造函數有多個參數,但是至多隻有一個沒有默認參數。例如:A(int i, double d1 = 0.0, double d2 = 1.2);這也會發生隱式轉換

爲了避免這種隱式轉換的發生,只需要在類的構造函數前面加上explicit關鍵字就可以了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章