作业6-多态
以后做完题一定要及时总结到博客里……不要拖着orz
而且我觉得作业都留的太巧妙了,不写作业掌握的都是假知识
1.看上去是多态
1 //程序填空产生指定输出 2 /* 3 输出 4 D::Fun 5 B::Fun 6 D::Fun 7 nBVal=2 8 nBVal=24 9 nDVal=8 10 B::Fun 11 nBVal=12 12 */ 13 #include <iostream> 14 using namespace std; 15 class B { 16 private: 17 int nBVal; 18 public: 19 void Print() 20 { cout << "nBVal="<< nBVal << endl; } 21 void Fun() 22 {cout << "B::Fun" << endl; } 23 B ( int n ) { nBVal = n;} 24 }; 25 // 在此处补充你的代码 26 class D:public B{ 27 int nDVal; 28 public: 29 void Print() 30 { 31 B::Print(); //覆盖,调用基类函数时要加B:: 32 cout << "nDVal="<< nDVal << endl; 33 } 34 void Fun() 35 {cout << "D::Fun" << endl; } 36 D ( int n ):nDVal(n),B(3*n){} 37 }; 38 int main() { 39 B * pb; D * pd; 40 D d(4); d.Fun(); 41 pb = new B(2); pd = new D(8); 42 pb -> Fun(); pd->Fun(); 43 pb->Print (); pd->Print (); //默认调用的是D中的Print 44 pb = & d; pb->Fun(); //为啥调用的是B的函数? 通过指针调用成员函数,只跟指针类型有关系 45 pb->Print(); 46 return 0; 47 }
备注:这道题叫看上去是多态实际上就不是多态。对于不是多态的情况,如果派生类和基类里有同名函数,就是覆盖关系,这是第五讲的内容,结果我都忘了……如果是派生类默认调用的是派生类的成员函数。对于非多态来说,通过指针调用成员函数,只跟指针类型有关系,也就是说指针类型决定了调用的是基类还是派生类的成员函数。我猜这道题的含义是,老师为了让我们体会多态的意义。因为不用多态,就不能实现用基类指针调用派生类的虚函数。
2.Fun和Do
1 /*A::Fun 2 C::Do*/ 3 #include <iostream> 4 using namespace std; 5 class A { 6 private: 7 int nVal; 8 public: 9 void Fun() 10 { cout << "A::Fun" << endl; }; 11 void Do() 12 { cout << "A::Do" << endl; } 13 }; 14 class B:public A { 15 public: 16 virtual void Do() 17 { cout << "B::Do" << endl;} 18 }; 19 class C:public B { 20 public: 21 void Do( ) 22 { cout <<"C::Do"<<endl; } 23 void Fun() 24 { cout << "C::Fun" << endl; } 25 }; 26 /*函数的参数传入的是B &p, 27 Fun函数没有多态,执行的是A(B中没有Fun这个函数,所以调用的是基类中的Fun,Do函数多态,执行的是C::Do*/ 28 void Call(//输入代码 派生类对象可以赋值给基类引用,然后看看是函数不是多态 29 B &p 30 ) { 31 p.Fun(); p.Do(); 32 } 33 int main() { 34 C c; 35 Call( c); 36 return 0; 37 }
备注:这道题就让填一个参数。这是多态的第二种应用,就是派生类对象可以赋值给基类引用。这道题里Call的实参就是一个B类对象,对于Fun函数来说,Fun不是多态,并且B中没有Fun函数,所以调用的就是A中的;对于虚函数Do来说,p.Do()就是多态,这时发现p是一个C类对象,所以调用的是C类的Do函数。
3.这是什么鬼delete
1 /* 2 destructor B 3 destructor A 4 */ 5 #include <iostream> 6 using namespace std; 7 class A 8 { 9 public: 10 A() { } 11 // 在此处补充你的代码 12 virtual ~A(){ cout << "destructor A" << endl; } 13 }; 14 class B:public A { 15 public: 16 ~B() { cout << "destructor B" << endl; } 17 }; 18 //我们知道一般析构顺序是派生类到基类,但是如果是基类的指针指向派生类, 19 //如果基类的析构函数不设置为虚函数,那么就程序就只会调用基类的析构函数,不会调用派生类的析构函数 20 //考察虚析构函数,一个类作为基类,析构函数应该设为虚函数 21 int main() 22 { 23 A * pa; 24 pa = new B; 25 delete pa; 26 return 0; 27 }
备注:
这道题就是考察虚析构函数,一个类作为基类,析构函数应该设为虚函数。
4.怎么又是Fun和Do
1 /* 2 A::Fun 3 A::Do 4 A::Fun 5 C::Do 6 */ 7 #include <iostream> 8 using namespace std; 9 class A { 10 private: 11 int nVal; 12 public: 13 void Fun() 14 { cout << "A::Fun" << endl; }; 15 virtual void Do() 16 { cout << "A::Do" << endl; } 17 }; 18 class B:public A { 19 public: 20 virtual void Do() 21 { cout << "B::Do" << endl;} 22 }; 23 class C:public B { 24 public: 25 void Do( ) 26 { cout <<"C::Do"<<endl; } 27 void Fun() 28 { cout << "C::Fun" << endl; } 29 }; 30 void Call( 31 // 在此处补充你的代码 32 A*p 33 ) { 34 p->Fun(); p->Do(); 35 } 36 int main() { 37 Call( new A()); 38 Call( new C()); 39 return 0; 40 }
备注:这道题又是填Call的参数,跟第二题差不多,只不过这是多态的第一种情况,通过指针来实现。