先把定义的类列出来
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();
分享到:
相关推荐
函数隐藏是指派生类中函数与基类中的函数同名,但是这个函数在基类中并没有被定义为虚函数,这种情况就是函数的隐藏。 所谓隐藏是指使用常规的调用方法,派生类对象访问这个函数时,会优先访问派生类中的这个函数,...
一、填空题(25 小题,共50 分) ...3.在基类和派生类中,派生类可以定义其基类中不具备的数据和操作。对两个有相同 名字的数据成员进行访问时,如果没有作用域分隔符限定时,对此数据成员的访问将出现 歧义。
控制方式 访问声明采用作用域"::" ,它的一般形式为:基类名::成员名;。在派生类的类界面中,将这些访问声明放在合适的访问控制保留字之后,从而改变在派生类中该成员的访问控制方式。 重定义 如果在派生类中定义了...
6.12章 类作用域 7.12章 构造函数 8.12章 友元 9.12章 static类成员 10.13章 复制构造函数和赋值操作符 11.13章 析构函数 12.13章 深复制、浅复制 13.13章 管理指针成员 14.14章 重载操作符的定义 ...
15.5.3 作用域与成员函数 499 15.5.4 虚函数与作用域 500 15.6 纯虚函数 502 15.7 容器与继承 503 15.8 句柄类与继承 504 15.8.1 指针型句柄 505 15.8.2 复制未知类型 507 15.8.3 句柄的使用 508 15.9 再谈文本查询...
覆盖:派生类中定义一个与基类数据成员或成员函数同名的成员,则替换基类的成员。 覆盖不是成员的重载,只是掩盖了从基类继承得到的同名成员,作用域声明后,仍可引用基类成员。可在派生类成员函数中引用基类...
鸡啄米:C++编程入门系列之三十六(继承与派生:派生类从基类继承 的过程) 鸡啄米:C++编程入门系列之三十七(继承与派生:派生类对基类成员 的访问控制之公有继承) 鸡啄米:C++编程入门系列之三十八(继承与...
13.作用域与生命期: 5 14.存储类和连接: 5 15.数组: 5 16.结构体和联合体: 5 17.指针运算符: 5 18.new,delete和动态对象: 6 19.指针选取和指针运算操作: 6 20.指针和数组的关系: 6 21.类的定义: 6...
- 第六节 变量的作用域与存储期 - 第七节 函数的重载 - 第八节 程序举例 - 本章小结 - 课后习题 ◇ 第六章 数组与字符串 - 课前索引 - 第一节 一维数组 - 第二节 二维数组 - 第三节 字符数组 - 第四节 ...
本文实例讲述了Python中的单继承与多继承。分享给大家供大家参考,具体如下: 单继承 一、介绍 Python 同样支持类的继承,如果一种语言不支持继承,类...BaseClassName(示例中的基类名)必须与派生类定义在一个作用域
9.10 将派生类对象隐式转换为基类对象 9.11 关于继承的软件工程 9.12 复合与继承的比较 9.13 对象的“使用”关系和“知道”关系 9.14 实例研究:类Point、CircIe和Cylinder 9.15 多重继承 小结 术语 自测练习 ...
9.10 将派生类对象隐式转换为基类对象 9.11 关于继承的软件工程 9.12 复合与继承的比较 9.13 对象的“使用”关系和“知道”关系 9.14 实例研究:类Point、CircIe和Cylinder 9.15 多重继承 小结 术语 自测练习 ...
15.6 继承中的类作用域 547 15.7 构造函数与拷贝控制 551 15.7.1 虚析构函数 552 15.7.2 合成拷贝控制与继承 552 15.7.3 派生类的拷贝控制成员 554 15.7.4 继承的构造函数 557 15.8 容器与继承 558 ...
自己整理的C++要背的一些概念,华南师范大学考c++的建议看看,21届考研有考到哦!!(可打印版) 1. 面向对象的三个基本特征 4 2. 抽象 4 ...72. 什么叫做作用域?什么叫做局部变量? 什么叫做全局变量? 14
15.6 继承中的类作用域 547 15.7 构造函数与拷贝控制 551 15.7.1 虚析构函数 552 15.7.2 合成拷贝控制与继承 552 15.7.3 派生类的拷贝控制成员 554 15.7.4 继承的构造函数 557 15.8 容器与继承 558 ...
如果某个派生类的部分或者全部直接基类是从另一个共同的基类派生而来,在这些俄直接基类中, 从上一级基类继承来的成员就拥有相同的名称,因此派生类中就会出现同名现象。对这种类型的同名成员也要使用作用域分辨符...
复习资料 1.1选择题 1.在一个C++程序中,main函数的位置( c )。 (a) 必须在程序的开头 (b) 必须在程序的后面 ( c ) 可以在程序的任何地方 (d) 必须在其它函数中间 2.... (a) 解释 (b) 汇编 (c) 编辑 (d) 编译 ...
(1)不在同一个作用域(分别位于派生类与基类) ; (2)函数名字相同; (3)参数相同; (4)基类函数必须有 virtual 关键字,不能有 static 。 (5)返回值相同(或是协变),否则报错;<—-协变这个概念我也...
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用: “派生”这个词汇,它和继承是一个意思,只是观察角度不同而已。换句话话,...
关于类的下列描述中,错误的是( )。 类是一组对象的模板 类是抽象数据的实现 类是数据和方法的封装体 类是对象的实例 ~D 关于对象的下列描述中,错误的是( )。... 派生类至少应有一个基类