在C++环境的世界中有这样两个概念,向上类型转换,向下类型转换,分别描述的是子类向基类和基类向子类的强制类型转换,因此可以在使用的过程当中感受到趣味性和吸引力。
- void swap(int &a,int &b)
- {
- //...
- }
- 2.请写出以下结构或类的大小(sizeof的输出值),并给出简要的解释.
- //A:
- typedef struct
- {
- char c1;
- char c2;
- int n;
- } stru;
- //B:
- class ClassA
- {
- public:
- int m_data1;
- int m_data2;
- void func1() { }
- void func2() { }
- virtual void vfunc1() { }
- virtual void vfunc2() { }
- };
- //C:
- struct ClassB {
- void f();
- };
- B::f(){
- }
有兴趣的看客可以先不看我下面的正确答案,试着作出自己的答案........
1.原题的考点就在于 Y() : b("b"), a("a"), X("base") {} 构造函数Y()冒号后面的这一串东西,说实话刚开始做的时候我只记得和初始化有关系,正确的名称其实是 "初始化参数列表".它的关键作用是在进入构造函数前完成对某些数据的初始化工作,在program1中的意思就是优先于Y()构造函数本身完成对象b和a的初始化,b("b"),a("a")就相当与X b(X("b"));X a(X("a")) 也就是通过拷贝构造函数完成。
2.可能有人要问 X("base")怎么这么用, 其实很简单,注意 Y 是X 的子类, 子类和父类构造函数的关系我想人人皆知,即先调用父类构造函数,这里的X("base")就是指定在调用Y()构造函数之前调用的父类X的构造函数是C++环境而不是 X(), 这里有些绕口,可以试着把 X("base")换成X(), 就明确具体的意思了。
3.最后一个关键点就是program1的结果输出顺序问题,我估计有些人的答案是 b , a ,base 或者 base , b ,a ,这里有两个意思, 第一,main 函数里申明 y, 所以正确执行顺序应该是 Y的父类X的构造函数(注意Y初始化参数列表中指明了Y的父类X究竟应该调用哪个构造函数)------>Y的私有成员变量的构造函数(注意Y初始化参数列表中指明了私有成员变量究竟应该调用哪个构造函数)------>Y的构造函数,对于program1 就是需要先调用X("base") ;
第二, 所有私有成员变量的构造函数的调用顺序与申明此变量的顺序保持一致,而跟调用变量的顺序无关,对于program1,调用Y构造函数调用私有变量顺序为先b后a, 而申明私有变量顺序为先a后b,所以后者是正确结果 ,综上,构造函数调用顺序依次为 X("base"),X("a"),X("b"),Y()
4.弄明白以上三点,我们再来看program2, 那就简单多了,program2没有任何trap,规规矩矩按照先父类构造,后私有变量构造,再子类构造的顺序,输出结果中的第一个XXX是Y的父类X的构造, 第二和第三个C++环境分别是类Y中变量a,b(注意顺序)的构造,最后是Y构造中的四输出。
就是static加上去看似很方便,但你怎么知道就应该分配256个字节呢?但是如果动态分配就要用到堆,那释放谁来释放呢?所以我个人认为最好的办法是这个函数加个str的参数,由客户程序员自己填。这样可以把错误控制住。但如果实在不愿意这样,我认为只能用智能指针了。关于智能指针就不展开说了,太多了。
【编辑推荐】