亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺析C++構(gòu)造函數(shù)虛擬化

 更新時間:2020年08月05日 15:08:18   作者:阿凡盧  
這篇文章主要介紹了C++構(gòu)造函數(shù)虛擬化的相關(guān)資料,文中講解非常細(xì)致,幫助大家更好的理解和學(xué)習(xí)c++構(gòu)造函數(shù),感興趣的朋友可以了解下

虛擬構(gòu)造函數(shù)

當(dāng)你有一個指針或引用,但是不知道其指向?qū)ο蟮恼鎸嶎愋褪鞘裁磿r,你可以調(diào)用虛擬函數(shù)來完成特定類型(type-specific)對象的行為。僅當(dāng)你還沒擁有一個對象但是你確切地知道想要對象的類型時,你才會調(diào)用構(gòu)造函數(shù)。那么虛擬構(gòu)造函數(shù)又從何談起呢?

例如假設(shè)你編寫一個程序,用來進(jìn)行新聞報道的工作,一條新聞報道由文字或圖片組成。你可以這樣管理它們:

class NLComponent { //用于 newsletter components 的抽象基類
public:
  ... //包含至少一個純虛函數(shù)
}; 

class TextBlock: public NLComponent {
public:
  ... // 不包含純虛函數(shù)
}; 

class Graphic: public NLComponent {
public:
  ... // 不包含純虛函數(shù)
};

class NewsLetter { // 一個 newsletter 對象由NLComponent 對象的鏈表組成
public: 
  NewsLetter(istream& str);
  ...

private:
  list<NLComponent*> components;
};

在NewsLetter中使用的list類是一個標(biāo)準(zhǔn)模板類(STL)。對象NewLetter不運行時就會存儲在磁盤上。為了能夠通過位于磁盤的替代物來建立Newsletter對象,讓NewLetter的構(gòu)造函數(shù)帶有istream參數(shù)是一種很方便的方法。當(dāng)構(gòu)造函數(shù)需要一些核心的數(shù)據(jù)結(jié)構(gòu)時,它就從流中讀取信息。此構(gòu)造函數(shù)的偽代碼是這樣的:

NewsLetter::NewsLetter(istream& str)
{
  while (str) {
    從str讀取下一個component對象;
    把對象加入到newsletter的 components
    對象的鏈表中去;
  }
}

或者,把這種技巧用于另一個獨立出來的函數(shù)叫做readComponent,如下所示:

class NewsLetter {
public:
  ...

private:
  // 為建立下一個NLComponent對象從str讀取數(shù)據(jù),
  // 建立component 并返回一個指針。
  static NLComponent * readComponent(istream& str);
  ...
};

NewsLetter::NewsLetter(istream& str)
{
  while (str) {
    // 把readComponent返回的指針添加到components鏈表的最后,
    // "push_back" 一個鏈表的成員函數(shù),用來在鏈表最后進(jìn)行插入操作。
    components.push_back(readComponent(str));
  }
}

考慮一下readComponent所做的工作。它根據(jù)所讀取的數(shù)據(jù)建立了一個新對象,或是TextBlock或是Graphic。因為它能建立新對象,它的行為與構(gòu)造函數(shù)相似,而且因為它能建立不同類型的對象,我們稱它為虛擬構(gòu)造函數(shù)。虛擬構(gòu)造函數(shù)是指能夠根據(jù)輸入給它的數(shù)據(jù)的不同而建立不同類型的對象。

虛擬拷貝構(gòu)造函數(shù)

還有一種特殊種類的虛擬構(gòu)造函數(shù)――虛擬拷貝構(gòu)造函數(shù)――也有著廣泛的用途。虛擬拷貝構(gòu)造函數(shù)能返回一個指針,指向調(diào)用該函數(shù)的對象的新拷貝。因為這種行為特性,虛擬拷貝構(gòu)造函數(shù)的名字一般都是copySelf,cloneSelf或者是象下面這樣就叫做clone。很少會有函數(shù)能以這么直接的方式實現(xiàn)它:

class NLComponent {
public:
  // declaration of virtual copy constructor
  virtual NLComponent * clone() const = 0;
  ...
};

class TextBlock: public NLComponent {
public:
  virtual TextBlock * clone() const // virtual copy constructor
  {
    return new TextBlock(*this);
  }
  ...
};

class Graphic: public NLComponent {
public:
  virtual Graphic * clone() const // virtual copy constructor
  {
    return new Graphic(*this);
  }
  ...
};

類的虛擬拷貝構(gòu)造函數(shù)只是調(diào)用它們真正的拷貝構(gòu)造函數(shù)。因此”拷貝”的含義與真正的拷貝構(gòu)造函數(shù)相同。如果真正的拷貝構(gòu)造函數(shù)只做了簡單的拷貝,那么虛擬拷貝構(gòu)造函數(shù)也做簡單的拷貝。如果真正的拷貝構(gòu)造函數(shù)做了全面的拷貝,那么虛擬拷貝構(gòu)造函數(shù)也做全面的拷貝。

注意上述代碼的實現(xiàn)利用了最近才被采納的較寬松的虛擬函數(shù)返回值類型規(guī)則。被派生類重定義的虛擬函數(shù)不用必須與基類的虛擬函數(shù)具有一樣的返回類型。如果函數(shù)的返回類型是一個指向基類的指針(或一個引用),那么派生類的函數(shù)可以返回一個指向基類的派生類的指針(或引用)。這不是C++的類型檢查上的漏洞,它使得又可能聲明象虛擬構(gòu)造函數(shù)這樣的函數(shù)。這就是為什么TextBlock的clone函數(shù)能夠返回TextBlock*和Graphic的clone能夠返回Graphic*的原因,即使NLCompo-nent的clone返回值類型為NLComponent*。

在NLComponent中的虛擬拷貝構(gòu)造函數(shù)能讓實現(xiàn)NewLetter的(正常的)拷貝構(gòu)造函數(shù)變得很容易:

class NewsLetter {
public:
  NewsLetter(const NewsLetter& rhs);
  ...

private:
  list<NLComponent*> components;
};

NewsLetter::NewsLetter(const NewsLetter& rhs)
{
  // 遍歷整個rhs鏈表,使用每個元素的虛擬拷貝構(gòu)造函數(shù)
  // 把元素拷貝進(jìn)這個對象的component鏈表。
  // 有關(guān)下面代碼如何運行的詳細(xì)情況,請參見條款35。
  for (list<NLComponent*>::const_iterator it = rhs.components.begin(); it != rhs.components.end(); ++it)
  {
    // "it" 指向rhs.components的當(dāng)前元素,調(diào)用元素的clone函數(shù),
    // 得到該元素的一個拷貝,并把該拷貝放到
    //這個對象的component鏈表的尾端。
    components.push_back((*it)->clone());
  }
}

遍歷被拷貝的NewsLetter對象中的整個component鏈表,調(diào)用鏈表內(nèi)每個元素對象的虛擬構(gòu)造函數(shù)。我們在這里需要一個虛擬構(gòu)造函數(shù),因為鏈表中包含指向NLComponent對象的指針,但是我們知道其實每一個指針不是指向TextBlock對象就是指向Graphic對象。無論它指向誰,我們都想進(jìn)行正確的拷貝操作,虛擬構(gòu)造函數(shù)能夠為我們做到這點。

以上內(nèi)容基本都來自《More Effective C++》。

以上就是淺析C++構(gòu)造函數(shù)虛擬化的詳細(xì)內(nèi)容,更多關(guān)于C++構(gòu)造函數(shù)虛擬化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論