C++中类的构造函数调用顺序
2015-09-23 17:02
441 查看
当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的
构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。
简而言之,对象是由“底层向上”开始构造的。因为,构造函数一开始构造时,总是
要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时,
如果无专门说明,就调用直接基类的默认构造函数。在对象析构时,其顺序正好相反。
下面的这个程序说明这个问题
总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关。
C++子类和父类的构造函数调用顺序
[cpp] view plaincopy
#include <iostream>
using namespace std;
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
};
int main()
{
drived d;
//输出结果
/*
i am base constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
由输出结果我们可以看到,先调用的是base类的构造函数,再调用了drived类的构造函数,也就是说,在声明子类实例的时候,是会先调用父类的构造函数的。这个很好理解,子类是包含了父类的信息的,所以要构造子类,必须先构造父类的信息,然后加入一些子类的新信息。
成员类的构造函数调用顺序[cpp] view plaincopy
#include <iostream>
using namespace std;
class son
{
public:
son()
{
cout<<"i am son constuction!"<<endl;
}
};
class family
{
public:
family()
{
cout<<"i am family constuction!"<<endl;
}
son jack;
};
int main()
{
family happyfamily;
//输出结果
/*
i am son constuction!
i am family constuction!
Press any key to continue
*/
return 0;
}
从上面的结果我们科看到,先调用的是构造函数。这是为什么?因为类中含有成员类时,先要给成员类申请空间,先调用成员类的构造函数,然后再调用自身的构造函数。
[cpp] view plaincopy
#include <iostream>
using namespace std;
//父亲姓名
class name
{
public:
name()
{
cout<<"i am name constuction!"<<endl;
}
};
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
name drivedname;
};
int main()
{
drived d;
//输出结果
/*
i am base constuction!
i am name constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
上面的例子是声明了一个name类,一个base类,一个drived类,其中drived类是从base类派生,且drived类中声明了name类的一个实例。那么根据我们上面的分析,我们声明了drived类之后,先会调用父类构造函数,也就是输出i am base construction,然后调用自身的成员类构造函数,也就是i am name construction,最后调用自身的构造函数,也就是i am drived construction。同理,如果我们在父类base类中声明了name成员类的话,顺序会是name->base->drived。我下面给出测试例子:[cpp] view plaincopy
#include <iostream>
using namespace std;
//父亲姓名
class name
{
public:
name()
{
cout<<"i am name constuction!"<<endl;
}
};
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
name drivedname;
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
};
int main()
{
drived d;
//输出结果
/*
i am name constuction!
i am base constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
构造函数,依次类推,直至到达派生类次数最多的派生次数最多的类的构造函数为止。
简而言之,对象是由“底层向上”开始构造的。因为,构造函数一开始构造时,总是
要调用它的基类的构造函数,然后才开始执行其构造函数体,调用直接基类构造函数时,
如果无专门说明,就调用直接基类的默认构造函数。在对象析构时,其顺序正好相反。
下面的这个程序说明这个问题
总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关。
C++子类和父类的构造函数调用顺序
[cpp] view plaincopy
#include <iostream>
using namespace std;
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
};
int main()
{
drived d;
//输出结果
/*
i am base constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
由输出结果我们可以看到,先调用的是base类的构造函数,再调用了drived类的构造函数,也就是说,在声明子类实例的时候,是会先调用父类的构造函数的。这个很好理解,子类是包含了父类的信息的,所以要构造子类,必须先构造父类的信息,然后加入一些子类的新信息。
成员类的构造函数调用顺序[cpp] view plaincopy
#include <iostream>
using namespace std;
class son
{
public:
son()
{
cout<<"i am son constuction!"<<endl;
}
};
class family
{
public:
family()
{
cout<<"i am family constuction!"<<endl;
}
son jack;
};
int main()
{
family happyfamily;
//输出结果
/*
i am son constuction!
i am family constuction!
Press any key to continue
*/
return 0;
}
从上面的结果我们科看到,先调用的是构造函数。这是为什么?因为类中含有成员类时,先要给成员类申请空间,先调用成员类的构造函数,然后再调用自身的构造函数。
[cpp] view plaincopy
#include <iostream>
using namespace std;
//父亲姓名
class name
{
public:
name()
{
cout<<"i am name constuction!"<<endl;
}
};
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
name drivedname;
};
int main()
{
drived d;
//输出结果
/*
i am base constuction!
i am name constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
上面的例子是声明了一个name类,一个base类,一个drived类,其中drived类是从base类派生,且drived类中声明了name类的一个实例。那么根据我们上面的分析,我们声明了drived类之后,先会调用父类构造函数,也就是输出i am base construction,然后调用自身的成员类构造函数,也就是i am name construction,最后调用自身的构造函数,也就是i am drived construction。同理,如果我们在父类base类中声明了name成员类的话,顺序会是name->base->drived。我下面给出测试例子:[cpp] view plaincopy
#include <iostream>
using namespace std;
//父亲姓名
class name
{
public:
name()
{
cout<<"i am name constuction!"<<endl;
}
};
//子类
class base
{
public:
base()
{
cout<<"i am base constuction!"<<endl;
}
name drivedname;
};
//父类
class drived : public base
{
public:
drived()
{
cout<<"i am drived constuction!"<<endl;
}
};
int main()
{
drived d;
//输出结果
/*
i am name constuction!
i am base constuction!
i am drived constuction!
Press any key to continue
*/
return 0;
}
相关文章推荐
- IOS开发笔记1-C语言笔记
- C/C++测试---判断输入的年月日是否合法
- 几大典型排序算法的c++代码实现及总结
- 不允许创建临时变量交换两个变量的内容
- More Effective C++ ——02_尽量使用C++风格的类型转换
- c++primer plus第十三章-虚函数virtual
- C++序列化方法 参考google protobuf
- 使用C++的类模板实现Stack类
- C++ 类访问控制
- C++ 多线程
- 设置一个临时变量交换两个变量的值
- C++ 预处理器
- 简要解读C++的动态和静态关联以及虚析构函数
- c/c++编程习惯
- Java和c++类实现单向链表
- C++ 动态内存
- More Effective C++ ——01_指针与引用的区别
- C语言高速入口系列(七)
- C++ 实现可变参数
- C语言register关键字—最快的关键字