基类与派生类的作用域

来源:互联网 发布:立体图纸设计软件 编辑:程序博客网 时间:2024/05/17 04:03

先把定义的类列出来

class Base{public:Base(int i = 0):val(i){}int getVal(){return val;};int getVal1(){return val;}void print(){cout<<"base"<<endl;}void getInt(){cout<<"do nothing"<<endl;}virtual void getNum(){cout<<"基类原函数"<<endl;};private:int val;};class Derived1:public Base{public:Derived1(int i = 0, int j = 1):Base(i),val(j){}int getVal(){return val;}void print(int i){cout<<"derived"<<endl;}int getInt(int a){return a;}void getNum(){cout<<"虚函数的重定义"<<endl;}int getNum(int a){cout<<"这是一个新的函数"<<endl;}private:int val;};class Derived2:public Base{void getNum(int){cout<<"Derived2"<<endl;}};


在C++中,名称的查找是由内自外的:对于一个派生类对象,先会在的派生类中查找名字,如果找到,就使用它;如果在它的作用域中找不到名字,就会在它的基类中查找:

Derived1 d;//使用派生类的函数cout<<d.getVal()<<endl;//派生类没有找到,使用基类的函数cout<<d.getVal1()<<endl;


这样做会有一个潜在的问题,派生类会屏蔽基类的成员,除非你显式的指定使用基类的成员:

//强制使用基类的函数cout<<d.Base::getVal()<<endl;


更要命的是,这种查找,是基于名字的,而不是基于函数原型的:即使基类和派生类中函数只是名字相同,但原型不同,屏蔽还是会发生,而不发生重载基类函数的情况:

//错误:基类中的void getInt()被屏蔽了//cout<<d.getInt()<<endl;//使用派生类中的函数cout<<d.getInt(3)<<endl;


看完了一般的规则,让我们再看看一些特殊的情况:

对于定义的了重载函数的派生类的对象,默认使用重载的函数,不是使用基类的函数:

//错误,派生类只能使用派生类重载的函数//d.print();d.print(3);

当然可以使用作用域操作符来指定基类的函数。
 

对于虚函数,由于动态绑定的作用,如果在派生类中找不到合适的函数,会到基类中去查找,而不会发生派生类屏蔽基类的结果:

Base bobj;Derived1 dobj1;Derived2 dobj2;Base *bp1 = &bobj,*bp2 = &dobj1,*bp3 = &dobj2;//调用基类的版本bp1->getNum();//由于形参不符,调用基类版本bp2->getNum();//掉用派生类版本bp3->getNum();


 

原创粉丝点击