C++的探索路16多态与虚函数之练习篇
Posted Guerrouj
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++的探索路16多态与虚函数之练习篇相关的知识,希望对你有一定的参考价值。
写出下面程序的输出结果
class A
public:
A()
virtual void func()
cout << "A::func" << endl;
~A()
virtual void fund()
cout << "A::fund" << endl;
;
class B :public A
public:
B()
func();
void fun()
func();
~B() fund();
;
class C :public B
public:
C()
void func()
cout << "C::func" << endl;
~C()
fund();
void fund()
cout << "C::fund" << endl;
;
int main()
C c;
return 0;
程序内容
程序中包含了A,B,C三个类,A派生出B,B派生出C。
A类中包含什么都不做的构造函数与析构函数,此外其还包含能够打印相应内容的虚函数func()以及fund()。
B类包含构造函数以及析构函数,其中构造函数中包含func(),析构函数中包含fund()。除了析构与构造函数,还包含fun()函数,fun()函数中调用func()函数。
C类包含构造函数与析构函数,构造函数什么都不做,析构函数包含fund()。除此外,其还包含func()与fund()
主程序中定义了C类的对象c。
运行分析
在整个程序运行的过程中包含了C类对象c的构造与析构过程。
而由前面基础内容可得两个知识点:
1,同参同返回类型的函数一旦定义为虚函数,则派生类的同参同返回函数也为虚函数。
2,析构函数与析构函数不存在多态的现象。即编译时可以确定哪个调用哪个。如果本类有该函数,调用本类;如果没有,调用直接基类;如果直接基类没有,调用间接基类.
按照顺序,首先是A类构造,什么都不做
然后B类构造,调用本类func(),func()不存在则往上找到A的func(),输出A::func
接着C类构造,什么也不做。
然后反向顺序析构:
先析构C,调用fund(),输出 C::fund
在调用B, 调用本类fund(),不存在,则往上找,输出A::fund
最后调用A,什么也不做。
结果
因此输出顺序为
A::func
C::fund
A::fund
运行验证
further
这里可能会有个疑问:
1,把A的fund()删掉会怎么样?
那当然是报错了->显示未定义标识符
2,A类的virtual关键字去掉?
显然并没有影响,人还是活的好好的,继续调用
下面程序的输出结果为
destructor B
destructor A
请写出完整的class A,限制条件:不得为class A编写构造函数
class A;
class B : public A
public:
~B() cout << "destructor B" << endl;
;
int main()
A*pa;
pa = new B;
delete pa;
return 0;
这个有点弱鸡,直接是书写虚构造函数。不写的话就直接是destructor B的输出了
class A
public:
virtual ~A()
cout<< "destructor A" << endl;
;
下面程序的输出结果是
A::Fun
A::Do
A::Fun
C::Do
请填空
class A
private:
int nVal;
public:
void Fun()
cout << "A::Fun" << endl;
virtual void Do()
cout << "A::Do" << endl;
;
class B :public A
public:
virtual void Do()
cout << "B::Do" << endl;
;
class C :public B
public:
void Do()
cout << "C::Do" << endl;
void Fun()
cout << "C::Fun" << endl;
;
void Call(_______)
p->Fun(); p->Do();
int main()
Call(new A());
Call(new C());
return 0;
程序分析
程序包含A,B,C三个类,A派生出B,B派生出C
这三个类均共有Do()函数以及Fun()函数,其中Do()函数至始至终从上到下都是虚函数,而Fun函数则不是虚函数,程序包含细节如下:
A类包含成员变量nVal,除此外还包含打印A::Fun的普通函数Fun()和能够打印A::Do的虚函数Do()
B类包含能够打印B::Do的虚函数Do(),其实这条语句加不加virtual并没有什么关系,因为基类某个函数声明为虚函数,那么派生类中,同名,同参数表的成员函数即使不写virtual关键字也自动成为虚函数。
C类包含打印C::Do的Do()函数以及打印C::Fun的Fun()函数
三个类外还包含Call()函数,形参未知,函数内部调用p指针分别指向Fun()以及Do()两个函数
主程序中两次调用Call函数,输入形参分别为new A()以及new C()
程序输出为
A::Fun
A::Do
A::Fun
C::Do
程序解答
写了这么一大串,作为练习感觉,效果不是很好,因为里面有技巧:
Call函数内部包含指针p,所以形参一定是个指针,什么类型呢,一般都是A类,如果定义为B或C的话,对于Call(new A())就运行不过去了
那就分析下这货为什么是这样
首先是
Call(new A),这一句没有多大波澜,直接指向A,也不存在虚函数会对最终结果产生什么波动,因此这条输出
A::Fun
A::Do
然后是
Call(new C),这一句稍微有点变化,因为存在虚函数Do()以及普通函数Fun()
对于虚函数则指向当前的对象:new出来的C,输出C::Do,而对于非虚函数Fun(),不存在多态捣乱则打印A::Fun
习题课总结
本部分的习题课有点波澜不惊,没有太大的难度;需要后续结合其他程序进行综合练习。
多态与虚函数这部分的重点在于:
1,如果函数运行为多态,则以指向调用的地址为准,进行相应的演化。
2,析构与构造函数不为多态,是直接调用的,如果本类不存在则向上寻找基类中的同名函数
3,虚析构函数能够使内存释放完全
以上是关于C++的探索路16多态与虚函数之练习篇的主要内容,如果未能解决你的问题,请参考以下文章