深度探索C++对象模型-----带有Default Constructor的member class object

         implicitly d efault constructor
        对于 class X ,如果没有任何User-declared constructor,那么会有一个default constructor被隐式(implicitly)声明出来....一个被隐式声明出来的default constructor将是一个trivial(浅薄而无能,没啥用的)constructor.
       class Foo{
        public :
            int val;
            Foo * pnext;
        }
        被合成出来的constructor只执行编译器所修的行动,也就是说,即使是需要为class Foo合成一个default constructor,那个constructor也不会将两个data member val和pnext初始化为0.


        带有Default Constructor的member class object
        如果一个class 没有任何constructor,但它内涵一个member Object ,而后者有default constructor,那么这个class的implicit default constructor就是 有用的。但是编译器不会帮初始化其他非Object成员,或者没有default constructor函数的member Object。
        在C++各个不同的编译模块中,编译器如何避免合成多个default constructor呢?解决办法是把合成的default constructor,copy constructor ,destructor,assignment copy operator都以inline方式完成。
        一个inline函数有静态链接,不会被文件以外者看到,如果函数太复杂,不适合做成inline,就会合成出一个explicit non-inline static 实例。
        
        以下程序片段,编译器为class Bar合成一个default constructor:
        class Foo{public:Foo();Foo(int),.....}
        class Bar{public Foo foo; char *str;}
        void foo_bar()
        {
            Bar bar;//Bar::foo必须在此处初始化。Bar::foo是一个member Object而其class Foo拥有default constructor。
            if(str){......}
        }
        这里被合成的Bar default constructor内含必要的代码,能够调用class Foo的default constructor来处理member Object Bar::foo,但是它并不产生任何代码来初始化Bar::str.将Bar::foo初始化是编译器的责任,将Bar::str初始化则是程序员的责任,被合成的default constructor看起来可能像这样:
        //Bar 的default constructor可能会像被这样合成
        //为member foo 调用class Foo的default constructor
        inline
        Bar::Bar()
        {
            //C++伪代码
            foo.Foo::Foo();
        }
        再一次注意,被合成的default constructor只满足编译器的需要,而不是程序的需求,为了让这个程序片段能够被正确执行,字符指针str也需要被初始化。


        
        我们假设程序员经由下面的default constructor提供了str的初始化操作:
        //程序员定义的default constructor
        Bar::Bar(){str = 0}
        
        现在程序的需求已经满足了,但是编译器还需要初始化member Object foo.
        由于default constructor已经被显式地定义出来,编译器没法合成一个,那么编译器会采取什么行动呢?
        编译器的行动是:
        如果class A内含一个或一个以上的member class Object,那么class A的每一个constructor必须调用每一个member class的default constructor。编译器会扩张已存在的constructor,在其中安插一些代码,使得User code在被执行之前,先调用必要的default constructors.延续前一个例子,扩张后的constructor可能像这样:
        //扩张后的default constructor
        //C++伪代码
        Bar::Bar()
        {
            foo.Foo::Foo();//附加上的compiler code
            str = 0 ;          //explicit User code 
        }

        如果有多个class member Object都要求constructor初始化操作,将如何?
        C++语言要求以“member object在class中声明顺序“来调用各个constructor。这一点由编译器完成,它为每一个constructor安插程序代码,以”member声明顺序“调用每一个member所关联的default constructor,这些代码将被安插在explicit User code之前。
        eg:
        class Dopey{ public :Dopey();......};
        class Sneezy{public: Sneezy();Sneezy(int);.....};
        class Bashful{public: Bashful();....};
        以及一个class Snow_White:
        class Snow_White{
            public:
                Dopey dopey;
                Sneezy sneezy;
                Bashful bashful;
            //....
            private :
                int numble;
        };
        如果Snow_White没有定义default constructor,就会有一个nontrivial constructor被合成出来,依序调用Dopey,Sneezy,Bashful的default constructor。然而如果Snow_White定义了下面这样的default constructor:
        Snow_White::Snow_White():sneezy(1024){
            numble = 0;
        }

        它会被扩张成:
        //编译器扩张后的default constructor
        // C++伪代码
        Snow_White::Snow_White():sneezy(1024)
        {
            //插入member class Object
            //调用其constructor
            dopey.Dopey::Dopey();
            sneezy.Sneezy::Sneezy(1024);
            bashful.Bashful::Bashful();
            
            //explicit user code
            numble = 0 ;
        }

    

















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值