《C++ Primer》第15章 面向对象程序设计
除了覆盖继承而来的虚函数之外,派生类最好不要重用其他定义在基类中的名字。
如果派生类(即内层作用域)的成员与基类(即外层作用域)的某个成员同名,则派生类将在其作用域内隐藏该基类成员。即使用派生类成员和基类成员的形参列表不一致。基类成员也仍然会被隐藏掉:
#include <iostream>
using std::endl;
using std::cout;
struct Base
{
int memfcn()
{
std::cout << "Base============memfcn()====" << endl;
return 0;
}
virtual int memfcn2()
{
std::cout << "Base============memfcn2()===" << endl;
return 0;
}
int memfcn3() const
{
std::cout << "Base============memfcn()====" << endl;
return 0;
}
};
struct Derived: public Base
{
int memfcn(int a) //隐藏基类的memfcn
{
std::cout << "Derived=========memfcn(a)===" << a << endl;
return a;
}
int memfcn2(int a)
{
std::cout << "Derived=========memfcn2(a)==" << a << endl;
return 0;
}
int memfcn3(int a)
{
std::cout << "Derived=========memfcn3(a)==" << a << endl;
return 0;
}
};
int main()
{
Derived d;
Base b;
b.memfcn();//调用Base::memfcn
d.memfcn(10);//调用Derived::memfcn
//d.memfcn();//错误:参数列表为空的memfcn被隐藏了
d.Base::memfcn();//正确,调用Base::memfcn
cout << endl;
b.memfcn2();
//d.memfcn2();//错误:参数列表为空的memfcn2被隐藏了
cout << endl;
b.memfcn3();
//d.memfcn3();//错误:参数列表为空的memfcn3被隐藏了
return 0;
}
运行结果:
15.6节 继承中的类作用域 习题答案
练习15.23:假设第550页的D1类需要覆盖它继承而来的fcn函数,你应该如何对其进行修改?如果你修改之后fcn匹配了Base中的定义,则该节的那些调用语句将如何解析?
【出题思路】
虚函数与其作用域的练习。
【解答】
550页的原程序如下:
#include <iostream>
#include <string>
using std::endl;
using std::cout;
using std::string;
class Base
{
public:
virtual int fcn()
{
cout << "Base====================fcn()====" << endl;
return 0;
}
};
class D1: public Base
{
public:
//隐藏基类的fcn(),这个fcn不是虚函数 D1继承了Base::fcn()的定义
int fcn(int a)//形参列表与Base中的fcn不一样
{
cout << "D1======================fcn()==a=" << a << endl;
return a;
}
virtual int f2()//是一个新的虚函灵敏,在Base中不存在
{
cout << "D1======================f2()=====" << endl;
return 0;
}
};
class D2: public D1
{
public:
int fcn(int a)//是一个非虚函灵敏,隐藏了D1::fcn(int)
{
cout << "D2======================fcn(a)=a=" << a << endl;
return a;
}
int fcn()//覆盖了Base的虚函数fcn
{
cout << "D2======================fcn()====" << endl;
return 0;
}
int f2()//覆盖了D1的虚函数f2
{
cout << "D2======================f2()=====" << endl;
return 0;
}
};
int main()
{
Base bobj;
D1 d1Obj;
D2 d2Obj;
Base *bp1 = &bobj, *bp2 = &d1Obj, *bp3 = &d2Obj;
bp1->fcn();//虚调用,将在运行时调用Base::fcn
bp2->fcn();//虚调用,将在运行时调用Base::fcn
bp3->fcn();//虚调用,将在运行时调用 D2::fcn
cout << endl;
D1 *d1p = &d1Obj;
D2 *d2p = &d2Obj;
//bp2->f2();//错误:Base没有名为f2的成员
d1p->f2();//虚调用,将在运行时调用D1::f12()
d2p->f2();//虚调用,将在运行时调用D2::f12()
cout << endl;
Base *p1 = &d2Obj;
D1 *p2 = &d2Obj;
D2 *p3 = &d2Obj;
//p1->fcn(42);//错误:Base中没有接受一个int的fcn
p2->fcn(42);//静态绑定,调用D1::fcn(int)
p3->fcn(42);//静态绑定,调用D2::fcn(int);
return 0;
}
运行结果:
要让D1类需要覆盖它继承而来的fcn函数则将D1类的fcn函数更改为int fcn()。修改后 p2->fcn(42),和p3->fcn(42)这两条调用语句将会出错。
修改代码重新运行结果如下: