北京大学MOOC C++程序设计 第六周测验

第六周学习的主要内容是虚函数和多态

1:看上去像多态

描述,程序填空产生指定输出

#include <iostream>
using namespace std;
class B { 
	private: 
		int nBVal; 
	public: 
		void Print() 
		{ cout << "nBVal="<< nBVal << endl; } 
		void Fun() 
		{cout << "B::Fun" << endl; } 
		B ( int n ) { nBVal = n;} 
};
int main() { 
	B * pb; D * pd; 
	D d(4); d.Fun(); 
	pb = new B(2); pd = new D(8); 
	pb -> Fun(); pd->Fun(); 
	pb->Print (); pd->Print (); 
	pb = & d; pb->Fun(); 
	pb->Print(); 
	return 0;
}

输入

输出

D::Fun
B::Fun
D::Fun
nBVal=2
nBVal=24
nDVal=8
B::Fun
nBVal=12

既然题干叫做看起来像多态,那么说明实际上不是多态呗。

从程序中可以看出,题目已经定义了类B,而main函数中还有一个类D,且B类指针可以接受D类对象的值,所以说明类D是类B的派生类。根据题干已知的程序和输出做比较,可以知道类D也有类B的构造函数,Print()和Fun()函数。分别按照输出分别写出这些函数即可。

#include <iostream>
using namespace std;
class B {
	private:
		int nBVal;
	public:
		void Print()
		{ cout << "nBVal="<< nBVal << endl; }
		void Fun()
		{cout << "B::Fun" << endl; }
		B ( int n ) { nBVal = n;}
};
//答案部分
class D:public B {
private:
    int nDval;
public:
    D (int n):B(3*n){nDval = n;}
    void Fun()
    {
        cout << "D::Fun" << endl;
    }
    void Print()
    {
        B::Print();
        cout << "nDVal="<< nDval << endl;
    }
};
//答案部分
int main() {
	B * pb; D * pd;
	D d(4); d.Fun();
	pb = new B(2); pd = new D(8);
	pb -> Fun(); pd->Fun();
	pb->Print (); pd->Print ();
	pb = & d; pb->Fun();
	pb->Print();
	return 0;
}

2:Fun和Do

答案:

#include <iostream> 
using namespace std;
class A { 
	private: 
	int nVal; 
	public: 
	void Fun() 
	{ cout << "A::Fun" << endl; }; 
	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( B &p ) {   //答案在这里
	p.Fun(); p.Do(); 
} 
int main() { 
	C c; 
	Call( c); 
	return 0;
}

这个题直接给答案,理解是B是C的父类,所以B类引用可以接受C类对象的值。Fun()函数不是虚函数,因此p.Fun()是直接调用了

B.Fun()函数,但是B没有实现Fun()函数,所以B调用了自己的父类A类的Fun()函数,所以输出 A::Do

Do()是虚函数,根据多态,p.Do()调用的是C.Do()函数,输出C::Do

3:这是什么鬼delete

答案:

#include <iostream>
using namespace std;
class A
{
public:
	A() { }
	virtual ~A(){cout << "destructor A" << endl;}
};
class B:public A {
	public:
	~B() { cout << "destructor B" << endl; }   //答案在这里
};
int main()
{
	A * pa;
	pa = new B;
	delete pa;
	return 0;
}

这个题的原理是:

虚析构函数
 通过基类的指针删除派生类对象时,通常情况下只调用基类的析构函数
 但是,删除一个派生类的对象时,应该先调用派生类的析构函数,然后调用基类的析构函数。
 解决办法:把基类的析构函数声明为virtual
 派生类的析构函数可以virtual不进行声明
 通过基类的指针删除派生类对象时,首先调用派生类的析构函数,然后调用基类的析构函数
 一般来说,一个类如果定义了虚函数,则应该将析构函数也定义成虚函数。或者,一个类打算作为基类使用,也应该将析构函数定义成虚函数。
 注意:不允许以虚函数作为构造函数

4:怎么又是Fun和Do

答案:

#include <iostream>
using namespace std;
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(A * p) {  //这里是答案
	p->Fun(); p->Do();
}
int main() {
	Call( new A());
	Call( new C());
	return 0;
}

这个题和第二题差不多。

甚至可以很明显的知道这里填A * p ,因为 如果填 B* p或者是 C * p那么main函数中的Call( new C());会报错,因为派生类指针无法接受基类对象emmm

猜你喜欢

转载自blog.csdn.net/qq_25406563/article/details/83048553