using namespace std;
int i = 0;
class A
{
public:
A() {cout << ++i << ". A()\n";}
~A() {cout << ++i << ". ~A()\n";}
};
class B
{
public:
B() {cout << ++i << ". B()\n";}
~B() {cout << ++i << ". ~B()\n";}
};
class C
{
public:
C() {cout << ++i << ". C()\n";}
~C() {cout << ++i << ". ~C()\n";}
};
class D
{
public:
D() {cout << ++i << ". D()\n";}
~D() {cout << ++i << ". ~D()\n";}
virtual void print() { cout << ++ i << ". D::print()\n";}
private:
B _b;
A _a;
};
class E : public D
{
public:
E() {cout << ++i << ". E()\n";}
~E() {cout << ++i << ". ~E()\n";}
void print() { cout << ++ i << ". E::print()\n";}
};
int main()
{
D * ptr = new E();
ptr->print();
delete ptr;
}
该题的运行结果是:
1. B()
2. A()
3. D()
4. E()
5. E::print()
6. ~D()
7. ~A()
8. ~B()
请各位大侠帮忙解释一下结果,拜谢。
8 个解决方案
#1
这个程序是有错误的,因为D里面有虚函数,析构函数却不是虚函数,所以会造成这样的结果
#2
要构造子类必须先构造基类,所以D()然后E(),D类里有A和B两个类的对象,所以成员变量要先构造结果就是B(),A(),D(),E()。然后是虚函数的调用,这个是多态的一个例子,父类的指针,指向继承类的对象,调用的方法是虚函数那么就会调用继承类的方法,然后是对象的删除,这里有个问题,D是基类,但是它的析构函数不是虚函数,这样尽管它指向了E的对象,但是E的析构函数却没有调用,这个是C++中的经典问题了,你的类要被人继承,那么析构函数就要是虚函数。
#3
1. 构造函数调用顺序,先基类,后派生类,按成员对象声明顺序构造类成员对象
2. 虚构顺序相反
2. 虚构顺序相反
#4
同意楼上
#5
其他的属于基本的,lz比较疑惑的应该在于第5行和第6行之间为什么没有输出 "6. ~E()".
只要把D的析构函数写成虚函数 virtual ~D() {cout <<++i <<". ~D()\n";}就可以输出这一行
这也是为什么推荐吧析构函数写成虚函数。试想,如果E的构造函数中new了内存,却没有调到~E()导致没有机会释放内存,势必造成内存泄漏。
只要把D的析构函数写成虚函数 virtual ~D() {cout <<++i <<". ~D()\n";}就可以输出这一行
这也是为什么推荐吧析构函数写成虚函数。试想,如果E的构造函数中new了内存,却没有调到~E()导致没有机会释放内存,势必造成内存泄漏。
#6
D * ptr = new E(); 这种用法在实际中用的还是比较广泛的,因为经常会用的,需要吧一个基类的几个派生类成员统一管理,这样都用基类指针变量来保存会很方便
#7
1,2,5楼的都对..
#8
mark, 构造函数先基类,再成员对象,再自身。
#1
这个程序是有错误的,因为D里面有虚函数,析构函数却不是虚函数,所以会造成这样的结果
#2
要构造子类必须先构造基类,所以D()然后E(),D类里有A和B两个类的对象,所以成员变量要先构造结果就是B(),A(),D(),E()。然后是虚函数的调用,这个是多态的一个例子,父类的指针,指向继承类的对象,调用的方法是虚函数那么就会调用继承类的方法,然后是对象的删除,这里有个问题,D是基类,但是它的析构函数不是虚函数,这样尽管它指向了E的对象,但是E的析构函数却没有调用,这个是C++中的经典问题了,你的类要被人继承,那么析构函数就要是虚函数。
#3
1. 构造函数调用顺序,先基类,后派生类,按成员对象声明顺序构造类成员对象
2. 虚构顺序相反
2. 虚构顺序相反
#4
同意楼上
#5
其他的属于基本的,lz比较疑惑的应该在于第5行和第6行之间为什么没有输出 "6. ~E()".
只要把D的析构函数写成虚函数 virtual ~D() {cout <<++i <<". ~D()\n";}就可以输出这一行
这也是为什么推荐吧析构函数写成虚函数。试想,如果E的构造函数中new了内存,却没有调到~E()导致没有机会释放内存,势必造成内存泄漏。
只要把D的析构函数写成虚函数 virtual ~D() {cout <<++i <<". ~D()\n";}就可以输出这一行
这也是为什么推荐吧析构函数写成虚函数。试想,如果E的构造函数中new了内存,却没有调到~E()导致没有机会释放内存,势必造成内存泄漏。
#6
D * ptr = new E(); 这种用法在实际中用的还是比较广泛的,因为经常会用的,需要吧一个基类的几个派生类成员统一管理,这样都用基类指针变量来保存会很方便
#7
1,2,5楼的都对..
#8
mark, 构造函数先基类,再成员对象,再自身。