zoukankan      html  css  js  c++  java
  • 关于拷贝构造

    有3种情况,可以将一个object的内容作为另外个object的初值:

    1. 明确的拷贝:X c_x2; X c_x = c_x2;

    2. 函数参数:void foo(X xx);

    3. 函数返回值:X foo() { X xx; return xx;};

    假如类的设计者定义了一个拷贝构造,比如:

    X::X( const X &x);

    Y::Y( const Y &y, int = 0);

    那么在大部分情况下,当一个类对象以另一个同类实体作为初值时,上述的构造会被调用。

    位逐次拷贝:

       1:  //...
       2:  Word noun("book");
       3:   
       4:  void foo()
       5:  {
       6:       Word verb  = noun;
       7:  }

    很明显,verb是根据noun来进行初始化。但如果没见过Word的声明,无法确定是否显式的声明了拷贝构造?如果没有声明,那么是否编译器会自动合成实体调用呢?

       1:  //声明方式1:语意拷贝
       2:  class Word
       3:  {
       4:  public:
       5:       Word(const char*);
       6:       ~Word(){delete []str;};
       7:  private:
       8:       int cnt;
       9:       char *str;
      10:  }

    在这样的拷贝声明下,当Word verb = noun时,verb和noun的str指针都指向相同的字符串“book”。因为Word(const char*)时,拷贝的并不是一个字符串内容,而是一个指向字符串“book”的指针(该指针指向字符串的地址)。这是灾难性的,一旦其中一个对象被销毁,另外个对象str指针便指向了一个危险的地址。

    如果采用另外种声明方式:

       1:  class Word
       2:  {
       3:  public:
       4:       Word(const Word &word);
       5:       ~Word();
       6:  private:
       7:       int cnt;
       8:       char *str;
       9:  }

    回忆下2个扩张操作:

    1. 增加一个“虚函数表”(vtbl),内含有每一个有作用的虚函数地址;

    2. 将一个指向虚函数表的指针(vptr),安插在每一个类对象内;

    所以这里的可怕点在于,vptr是否被正确设置好初值(如果没有指向正确的vtbl,那么后果会很严重)。

     1 class ZooAnimal
     2 {
     3 public:
     4      ZooAnimal();
     5      virtual ~ZooAnimal();
     6      
     7      virtual void animate();
     8      virtual void draw();
     9 private:
    10      // 各种数据
    11 }
    12 
    13 class Bear : public ZooAnimal
    14 {
    15 public:
    16      Bear();
    17      void animate();
    18      void draw();
    19      virtual dance();
    20 private:
    21      // 各种数据
    22 }

    然后这样:

    Bear weini;
    
    Bear huangseweini = weini;

    这里的Bear类对象以另外一个Bear对象作为初值,都是依靠位拷贝来完成。

    首先weini对象,先由Bear默认构造来完成初始化,这里的vptr(weini)被设定指向Bear类对象的虚表(这里由编译器安插代码来完成)。所以,把weini的vptr指针拷贝给huangseweini的vptr是安全的。

    image

    当一个基类对象以其子类作为对象内容进行初始化时,势必发生切割行为。此时vptr的复制操作也必须保证安全。

       1:  void draw(const ZooAnimal &zoey){ zoey.draw();};
       2:  void foo() {
       3:       ZooAnimal franny = weini;
       4:       draw(weini);     // 这里调用的是Bear::draw()的接口 
       5:       draw(franny);    // 这里调用的仍然是ZooAnimal::draw()的接口
       6:  }
    image 
    也就是说,合成出来的ZooAnimal拷贝构造会明确的设定对象的vptr指向ZooAnimal的虚表,而不是直接从右手边的对象中将其vptr拷贝过来。
     
  • 相关阅读:
    Year Outline stat Detail stat 1987--1996----1999 C:UsersATIDocuments00drmmr v2 tafdrmmr1987-20
    atitit 2010 2010 diary log events memorabilia v3 taf .docx No finish , wait to finish 1.6 yLu
    Atitit 标记语言ML(Markup Language) v4 目录 1. 标记语言ML Markup Language 1 1.1. 简介 1 2. 置标语言置标语言通常可以分为三类:标识性的
    Atitit 2001drmmr v1 t05.docx 1.1shoeho kh majyao n chfe ,bg n rjywel ycyi ,shwa leihaivvei yaopao
    Atitit nlp重要节点 v3 目录 1. 语法分析重点 节点余额365个 1 2. nlp词性表 2 2.1. 词语分类13类 2 2.2. 副词 约20个 3 2.3. 代词30个 3 2
    Atitit 提升语法级别4gl 4.5g 4.9g 5g 目录 1. 语言级别表 1 2. 4.9g实现细节 2 2.1. $dollor前导符 2 2.2. Static变量 2 2.3. S
    Atitit 工程师程序员技术级别对应表与主要特征 P1--p6 说明 类别 职称 对应技术标志 P5 高级工程师 工程师类 一般四五年 P6 资深开发 工程师类 78年经历 P7 P7
    Atitit 自然语言与人工语言的语法构建ast的异同点 目录 1. 语言节点gaishu。。 2 1.1. 节点、函数数量大约200个 2 1.2. 关键词节点 是 有 的 3 1.3. 标识符
    Atitit 编程语言的block概念 目录 1. 匿名block 1 1.1. 函数块 方法快 1 1.2. Sp udf块 1 2. 实现block的方式 1 2.1. 早期的语言大多是采用en
    Atitit 效率提升法细则 v3 t028.docx Atitit 提升效率细则 目录 1. 目标 2 1.1. 配置化增加扩展性 尽可能消除编译 方便增加 调整业务逻辑 2 1.2. 统一接口
  • 原文地址:https://www.cnblogs.com/davidsguo008/p/3652773.html
Copyright © 2011-2022 走看看