今天在写一个类的继承,在调试的时候,虚函数的特点并没有体现出来,让我很是不解,用了两个编译器,结果都是一样的。
类的代码是这样的:
1 #ifndef CLASSBRASS_H_INCLUDED 2 #define CLASSBRASS_H_INCLUDED 3 #include <iostream> 4 #include <cstdlib> 5 6 using namespace std; 7 //extern int a; 8 class Brass 9 { 10 private: 11 char *name;//the name of this account 12 unsigned int accnum;//account number 13 int balance;//balance has the meaning of the left money 14 public: 15 //Brass(); 16 //it should be canceled due to There is no need to creat it 17 //if there is no default constructor,you shall never creat a object without arguments(No 'e') 18 Brass(const char *n="B:noname",unsigned int a=0x0FFFFFFF,int b=0); 19 Brass(const Brass & B);//this function is used when a new object is created by a existed object 20 virtual ~Brass();//virtual used only declaration 21 void Deposit(double amount);//not virtual 22 virtual void Withdraw(double amount);//virtual function must be with definition 23 double Balance()const;//return the balance 24 virtual void ViewAccount()const;//there is no position recmond of virtual and void 25 //basic class 26 void test(Brass TT); 27 void virtual out(); 28 }; 29 //inheritance of brass 30 class BrassPlus:public Brass 31 { 32 private: 33 double maxloan; 34 double rate; 35 double owesBank; 36 public: 37 BrassPlus(double ml=500,double ra=0.10,char * na="BP:noname",unsigned ac=0x0FFFFFFF,int ba=0.0); 38 BrassPlus(Brass &br,double ml,double ra); 39 virtual ~BrassPlus();//each destructure is virtual 40 //rewrited function 41 void ViewAccount(); 42 void Withdraw(double amount); 43 //new functions 44 void ResetMaxloan(double); 45 void ResetRate(double ); 46 void ResetOwesBank(double); 47 //Dynamic Binding 48 void out(); 49 }; 50 #endif // CLASSBRASS_H_INCLUDED
Brass是基类,BrassPlus是派生类。大家可以观察一下22行和41行的代码,你会发现一点区别。除了virtual外,那就是一个声明了const,而在派生中并没有这个const。
我之前的测试的是用Brass的指针指向BrassPlus的类,然后用Brass的指针调用BrassPlus修改了的成员函数,也就是ViewAccount()。按照书上(C++ Primer Plus,P449)中所讲,编译器对虚方法使用动态联编,在程序运行时才能确定对象的类型。在main函数中我创建一个Brass指针和BrassPlus对象,然后用Brass指针指向BrassPlus对象。就是这样
1 int main() 2 { 3 cout << "Hello world!" << endl; 4 BrassPlus ASD,*BPT; 5 Brass Btemp,*BT; 6 BT=&ASD; 7 BT->ViewAccount(); 8 system("PAUSE"); 9 return 0; 10 }
然后用那个指针调用ViewAccount()函数。预期结果应该是使用派生类的函数,而结果却是基类的函数。很简单的一个类的测试在这出现了问题。
出错的原因就是因为派生类中ViewAccount()函数没用声明为const类型。因为缺少这个const,编译器并没有将基类的ViewAccount函数视为派生类ViewAccount()函数的虚方法。所以,在使用BT->ViewAccount()时,用的就是基类的函数,而不是派生类的。因为同名且不是虚方法,会被基类的函数屏蔽掉。
细节决定成败。
若有错误,请指正,将非常感谢。