在使用new创建对象时,主要完成四项工作:
1 构造父类成员对象
2 构造子类成员对象
3 调用父类构造函数
4 调用子类构造函数
这四项工作的时间顺序是怎样的呢?
原则是:先父类后子类,先成员后函数
一级继承
例如:
class X{
public:
X(){cout<<"X";}
};
class A{
public:
X x1;
A(){cout<<"A";}
};
class B: public A{
public:
X x2;
B(){cout<<"B";}
};
int main(){
B b;
}
构造对象B时,根据第1个原则:先父类后子类,先构造A(1),然后构造B(2)。
构造A(1):
然后根据第2个原则,先成员后函数,先构造A的成员x1,即先调用X构造函数,然后再调用A构造函数
构造B(2):
根据第2个原则,先成员后函数,先构造B的成员x2,即先调用X构造函数,然后再调用B构造函数
因此输出为:
XAXB
多级继承
在一级继承中这个比较容易分析,在多级继承中就会复杂些,但坚持这两个原则,细心分析也不会出问题的。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
class X{
public:
X(){cout<<"X";}
};
class Y{
public:
Y(){cout<<"Y";}
};
class A{
public:
A(){cout<<"A";}
~A(){cout<<"~A";}
};
class B: public A{
public:
Y x;
A a;
Y y;
B(){cout<<"B";}
~B(){cout<<"~B";}
};
class C: public B{
protected:
X x;
B b;
A a;
X y;
public:
C(){cout<<"C";}
~C(){cout<<"~C";}
};
int main(){
C *c = new C();
delete c;
}
这个程序的输出就比较复杂:
AYAYBXAYAYBAXC~C~A~B~A~A~B~A~A
开始分析:
先父类后子类,所以先构造B(1),然后构造C(2)
构造B(1)的过程如下:
也是先构造A(1.1),然后构造B(1.2)
构造A(1.1)的过程如下:
调用A的构造函数,输出A(第一个输出字符)
构造B(1.2)的过程如下:
先成员(1.2.1)后构造(1.2.2),
成员(1.2.1)的过程如下:
B的成员有Y,A,Y,所以构造Y,A,Y,输出YAY(第二到四个字符)
构造(1.2.2)的过程如下:
B的构造函数,输出B(第五个字符)
所以构造B一共会输出YAYB四个字符
构造C(2)的过程如下:
先成员(2.1)后构造(2.2)
成员(2.1)的过程如下:
C的成员有XBAX
所以构造X,输出X(第六个字符)
构造B输出AYAYB(第七到十一个字符)
构造A输出A(第十二个字符)
构造X输出X(第十三个字符)
构造(2.2)
输出C(第十四个字符)
最后按照完全相反的顺序调用析构函数
来自http://hankjin.blog.163.com/blog/static/33731937201010633157934/
相关推荐
如果子类定义了构造函数,那么子类的构造函数不会自动调用父类的构造函数。如果想要执行父类的构造函数,必须在子类构造函数中显式调用parent::__construct()。如果子类没有定义构造函数,PHP会尝试调用父类的构造...
在面向对象编程中,构造函数和析构函数拥有特殊的用途和调用时机。 构造函数是在创建对象时自动调用的特殊函数,其主要作用是初始化对象的状态,例如设置对象的属性值。在PHP中,构造函数被命名为`__construct`。...
2. **显式调用父类构造函数**:在子类构造函数中通过`Parent.call(this, ...)`的方式显式调用父类构造函数。 3. **使用ES6的类语法**:ES6引入了新的类语法,使得类和继承的编写更加直观和简洁。 #### 七、结论 ...
12. **初始化成员列表的使用场景**:初始化常量成员、没有无参构造函数的对象成员、引用成员时需要使用。 13. **常对象**:常对象的成员不可修改,确保对象的不变性。 14. **静态成员函数**:静态成员函数不与特定...
11. 构造函数调用顺序:首先调用基类构造函数,然后按照成员变量声明的顺序初始化,最后执行类自己的构造函数体。 12. 初始化成员列表的必要情况:常量成员、无参数构造函数的对象成员、引用成员的初始化必须在初始...
12. **初始化成员列表的必要性**:常量成员、没有无参构造函数的对象成员、引用成员必须在初始化列表中初始化。 13. **常对象**:常对象一旦创建,其成员无法被修改,提供了一种强制不可变性的机制。 14. **静态...
4. **构造函数调用**:最后,调用类的构造函数完成对象的构建。 #### 问题分析 在案例中,`ChildDlg2`类中的`JTextField`变量在类变量声明时即被初始化,而`ChildDlg1`则是在构造函数中进行初始化。问题出在`...
3. 析构函数调用时机:析构函数在对象生命周期结束,即将被删除时自动调用。选项C正确。 4. inline关键字:inline用于请求编译器将函数展开为它的本体,以减少函数调用的开销。对于短小且频繁调用的函数,使用...
析构函数的调用时机 析构函数在对象生命周期结束时被自动调用,例如当对象离开作用域或显式删除动态分配的对象时。 #### 23. 对象间的资源共享 对象可以通过类的静态成员变量实现数据共享。静态成员变量是所有对象...
2. **拷贝构造函数的调用时机** - 当一个对象用于初始化另一个对象时。 - 函数参数传递时,如果参数类型是对象类型,则会调用拷贝构造函数。 - 函数返回值是对象类型时,返回时会调用拷贝构造函数。 3. **构造...
8. **拷贝构造函数的调用时机**: - 类的一个对象去初始化该类的另一个对象时; - 如果函数的形参是类的对象,调用函数进行形参和实参结合时; - 如果函数的返回值是类对象,函数调用完成返回时。 9. **构造函数...
- 类的成员是对象成员,而该对象没有无参构造函数。 - 类的成员为引用类型。 #### 三、类的高级特性 **13. 常对象** 常对象不允许修改其成员的值,通常用于保护对象的状态不变性。 **14. 静态函数的意义** 静态...
本文档总结了C++中的重要知识点,涵盖了构造函数、虚函数、静态成员、重载、重写、成员函数、全局函数、友元函数、继承、面向对象特点、常引用和断言等方面的知识。 1. 构造函数不能声明为虚函数的原因:因为虚函数...
拷贝构造函数的调用时机主要有三种,即当一个对象用来初始化另一个同类对象时、函数的形参是类对象时,以及函数返回类对象时。构造函数用于初始化对象,与普通函数不同的是,构造函数的名字必须与类名相同,并且不...
构造函数是一种特殊的成员函数,用于初始化对象的成员变量。构造函数没有返回类型,并且名称与类名相同。与普通函数相比,构造函数在创建对象时自动调用,并且通常不接受返回值。 #### 10. 必须重写拷贝构造函数的...
- 成员对象没有无参构造函数时。 - 成员为引用时。 **13. 常对象的概念** 常对象是在其生命周期内其成员变量不可更改的对象。创建常对象时,需要使用`const`关键字。 **14. 静态函数的作用** - 可以通过类名直接...
- **区别于普通函数**: 构造函数在对象创建时自动调用,而普通函数需显式调用。 **1.5 Return 关键字** - **作用**: 用于从方法中返回特定结果。 - **注意**: - 结果类型必须与方法的返回值类型一致。 - 即便...
- **自动调用**:静态构造函数会在程序首次创建类的实例或引用任何静态成员时自动调用,这使得开发者无法控制其执行时机。 - **唯一性**:每个类只能有一个静态构造函数,不允许定义多个。 - **与实例构造函数...
- **执行时机**:对象创建时,会自动调用相应的构造函数。 - **语法**:构造函数无返回值类型,以类名命名,可以带参数。 - **自动添加**:如果类中未定义构造函数,Java会自动添加一个无参数的构造函数。 5. **...
选项A描述的是错误的,对象成员构造函数并不会先于基类构造函数执行。 3. 虚函数与动态联编 在C++中,动态联编是指在运行时决定调用哪个函数的过程,这通常通过虚函数实现。要实现动态联编,必须在基类中将成员函数...