• 【C++学习】类初始化列表的分析总结


    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/

    1.在子类构造时完成父类(没有默认构造函数)的初始化参数传入:

    #include <iostream>
    
    class Foo
    
    {
    
            public:
    
            Foo( int x ) 
    
            {
    
                    std::cout << "Foo's constructor " 
    
                              << "called with " 
    
                              << x 
    
                              << std::endl; 
    
            }
    
    };
    
    class Bar : public Foo
    
    {
    
            public:
    
            Bar() : Foo( 10 )  // construct the Foo part of Bar
    
            { 
    
                    std::cout << "Bar's constructor" << std::endl; 
    
            }
    
    };
    
    int main()
    
    {
    
            Bar stool;
    
    }

    2.初始化const成员和reference成员

    #include <iostream>
    
    using namespace std;
    
    class const_field
    
    {
    
            public:
    
                    const_field(int ii) : _constant( 1 ),ref( i ) { i=ii; }
    
                    int geti(){return i;}
    
                    int getref(){return ref;}
    
            private:
    
                    const int _constant;
    
                    int &ref;
    
                    int i;
    
    };
    
    int main()
    
    {
    
            const_field cos(100);
    
            cout << cos.geti() <<" " << cos.getref()<<endl;
    
    }
    

     

    注:初始化列表在构造函数函数体运行之前完成,在构造函数函数体运行中,数据成员的设置是赋值,而不是初始化。初始化阶段可以是显式或隐式的,这要取决于类成员的类型,对于built-in成员其实都一样,但是对于类成员,是否存在成员初始化表则有所不同:若不存在则是隐式初始化,按照声明的顺序依次调用所有类成员函数所属基类的默认构造函数(见后边的练习),在函数体内有赋值动作调用赋值构造函数。若存在则属于显式初始化,类成员使用复制构造函数完成初始化,这也就是我们有时会说在初始化列表中初始化开销会小些的原因(因为若在函数体内再赋值,那么类成员函数的默认构造函数执行所做的工作都是无用功),例如:

    Account(){

       _name = “”:

       _balance=0.0;

    }

    这里面的string型的_name在赋值前已经被初始化阶段隐式初始为空串(调用了string的默认构造函数),所以在函数体中的赋值是完全没有意义的。

    总之,建议使用初始化列表(注意是按照成员声明顺序,而不是列表顺序)来做对象创建时初始化工作。

    初始化顺序为:

    1. 基类
    2. 成员数据成员(初始化列表)
    3. 构造函数函数体

    附:练习

    #include <iostream>
    
    using namespace std;
    
    class Test
    
    {
    
    public:
    
     Test()
    
     {
    
      ctor_count++;
    
      cout<<"ctor "<<ctor_count<<endl;
    
     }
    
     Test(const Test & r)
    
     {
    
      ctor_count++;
    
      cout<<"copy ctor "<<ctor_count<<endl;
    
     }
    
     Test & operator= (const Test& r)
    
     {
    
      ctor_count++;
    
      cout<<"assignment op "<<ctor_count<<endl;
    
      return *this;
    
     }
    
    private:
    
     static int ctor_count; //only a declaration
    
    };
    
    int Test::ctor_count=0; // definition + initialization
    
    class Task
    
    {
    
    private:
    
     int pid;
    
     Test name; // type changed from string to Test
    
    public:
    
     Task (int num, const Test & n) {pid=num; name=n;}
    
    };
    
    int main(void)
    
    {
    
     Test t;
    
     Task task(1, t);
    
     return 0;
    
    }
    

    运行结果:

    [root@localhost ~]# ./a.out
    
    ctor 1
    
    ctor 2
    
    assignment op 3
    

    解释:static int是为了更好的说明问题,不要被这个类型所迷惑。第一行表示程序在构造t。第二行表示默认初始化时调用默认构造函数,第三行是构造task时的赋值。

    将程序的初始化修改:

    Task (int num, const Test & n):pid(num),name(n) {}

    运行结果是:

    ctor 1
    copy ctor 2

    下边的这个程序也可以说明问题,如果还不理解上例的话:

    #include <iostream>
    
    using namespace std;
    
    class Bar
    
    {
    
    public:
    
      Bar();
    
      Bar(int x);
    
      Bar & operator=(const Bar& bar)
    
      {
    
          cout <<"Assignment Bar constructed." <<endl;
    
      }
    
      Bar(const Bar &bar)
    
      {
    
          cout <<"Copy Bar constructed." <<endl;
    
      }
    
    private:
    
      int x;
    
    };
    
    Bar::Bar()
    
    {
    
      std::cout << "Bar default-constructed." << std::endl;
    
    }
    
    Bar::Bar(int x) : x(x)
    
    {
    
      std::cout << "Bar constructed." << std::endl;
    
    }
    
    class Foo
    
    {
    
    public:
    
      Foo(Bar bar);
    
    private:
    
      Bar bar;
    
    };
    
    Foo::Foo(Bar bar)
    
    {
    
      this->bar = bar;
    
    }
    
    //Foo::Foo(Bar bar):bar(bar){}
    
    int main()
    
    {
    
        Foo foo(Bar(3));
    
        return 0;
    
    }
    

    作者:gnuhpc
    出处:http://www.cnblogs.com/gnuhpc/


                   作者:gnuhpc
                   出处:http://www.cnblogs.com/gnuhpc/
                   除非另有声明,本网站采用知识共享“署名 2.5 中国大陆”许可协议授权。


    分享到:

  • 相关阅读:
    JavaSE知识-18(Map集合&模拟斗地主洗牌和发牌)
    JavaSE知识-17(Set集合)
    20145231 《信息安全系统设计基础》 课程总结
    20145231 《信息安全系统设计基础》第14周学习总结
    20145231 《信息安全系统设计基础》第13周学习总结
    20145231 《信息安全系统设计基础》第12周学习总结
    20145231 20145205 《信息安全系统设计基础》实验五
    20145231 《信息安全系统设计基础》第11周学习总结
    20145231 20145205 《信息安全系统设计基础》 第三次实验
    20145231 《信息安全系统设计基础》第10周学习总结
  • 原文地址:https://www.cnblogs.com/gnuhpc/p/2811926.html
Copyright © 2020-2023  润新知