当前位置:
文档之家› C++虚函数相关练习及答案分析
C++虚函数相关练习及答案分析
调用该函数,观测并分析输出的结果。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;A::func();}
virtual void func(){cout<<"A::func()"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;}
void func(){cout<<"D::func()"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
};
class B:public A
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;B::func();}
void func(){cout<<"B::func()"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
D d;
};
class C:public B
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
};
class B:public A
{
public:
D d;
B(){cout<<"调用B的构造函数"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
};
int main(void)
{
A *p =new B;
delete p;
return 0;
}
运行结果:
将A的析构函数不设置为虚析构函数时的代码:
#include <iostream>using namespac std;class A
{
1、A,B,C,D四个类,分别是B继承于A,C继承于B,其中B类中内嵌一D对象,
在main函数中构造一C对象,观测构造函数和析构函数的调用顺序。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
{
public:
C(){cout<<"调用C的构造函数"<<endl;C::func();}
void func(){cout<<"C::func()"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
return 0;
}运行结果:
结果分析:
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
virtual ~A(){cout<<"调用A的虚析构函数"<<endl;}
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
在主函数中创建一个C的对象,分别调用A、B、C的构造函数,基类和派生类中都调用了自己的func()函数。
4、有类A,派生出类B,有如下代码
A *p = new B;
delete p;
观察并分析将A的析构函数设置或不设置为虚析构函数的表现。
将A的析构函数设置为虚析构函数时的代码:
#include <iostream>
构造类C的对象时,因为C继承于B,B继承于A,且在B类中内嵌了D的对象,所以创建C的对象时,先调用A的构造函数,然后再调用内嵌对象d的构造函数,然后调用B的构造函数,然后调用C的构造函数,然后依次反向调用析构函数。当类之间存在继承关系时,创建对象时总是从最远(最里层)的类开始创建。
2、给上题A类增加一虚函数func,并要求B/C派生类也提供该函数实现,并实验分别以指针、引用
cout<<"------------指针对象方式访问----------------"<<endl;
A *aa = new C;
aa->func();
cout<<"------------引用对象方式访问----------------"<<endl;
A &aaa = c;
aaa.func();
return 0;
public:
A(){cout<<"调用A的构造函数"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class B:public A
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
~B(){cout<<"调用B的析构函数"<<endl;}
};
int main(void)
void func(){cout<<"C::func()"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
cout<<"------------普通对象方式访问----------------"<<endl;
A a = c;
a.func();
{
A *p =new B;
delete p;
return 0;
}
运行结果:
结果分析:
当一个类作为基类时,应该将其析构函数声明为虚析构函数,这样做的目的是为了当基类的一个指针指向派生类的对象时,派生类的析构函数会被调用。
~B(){cout<<"调用B的析构函数"<<endl;}
};
class C:public B
{
public:
C(){cout<<"调用C的构造函数"<<endl;}
~C(){cout<<"调用C的析构函数"<<endl;}
};
int main(void)
{
C c;
return 0;
}
运行结果:
结果分析:
和普通对象方式访问该虚函数时的输出,并分析原因。
代码:
#include <iostream>
using namespace std;
class A
{
public:
A(){cout<<"调用A的构造函数"<<endl;}
virtual void func(){cout<<"A::func()"<<endl;}
~A(){cout<<"调用A的析构函数"<<endl;}
};
class D
{
public:
D(){cout<<"调用D的构造函数"<<endl;D::func();}
void func(){cout<<"D::func()"<<endl;}
~D(){cout<<"调用D的析构函数"<<endl;}
}
运行结果:
结果分析:
在主函数中创建A的对象,虽然A a = c,但是a是基类的对象,没有指向或者引用子类,所以当a调用func时,调用的是类A中的虚函数;而aa和aaa分别指向和引用了C的对象,所以其调用的是类C中的虚函数func(),而不是基类中的func()
3、给上题A类增加一虚函数func,并要求B/C派生类也提供该函数实现,并实验在不同类的构造函数、析构中
{
public:
B(){cout<<"调用B的构造函数"<<endl;}
void func(){cout<<"B::func()"<<endl;}