继承中的类作用域
每个类定义自己的作用域,在这个作用域内我们定义类的成员。
当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内。如果一个名字在派生类的作用城内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义。
派生类的作用域位于基类作用域之内这一事实可能有点儿出人意料,毕竟在我们的程中派生类和基类的定义是相互分离开来的。不过也恰恰因为类作用域有这种继承嵌系,所以派生类才能像使用自己的成员一样使用基类的成员。
例如,当我们编写下面代码时:
class Quote
{
string isbn()
{}
};
class Disc_quote:public Quote
{};
class Bulk_quote:public Disc_quote
{
};
Bulk_quote bulk;
cout << bulk.isbn();
名字isbn的解析将按照下述过程所示:
- 因为我们是通过Bulk_quote的对象调用isbn的,所以首先在Bulk_quote中查找,这一步没有找到名字isbn。
- 因为Bulk_quote是Disc_quote的派生类,所以接下来在Disc_quote中查找,仍然找不到。
- 因为Disc_quote是Quote的派生类,所以接着查找Quote;此时找到了名字isbn,所以我们使用的isbn最终被解析为Quote中的isbn。
编译时进行名字查找
一个对象、引用或指针的静态类型决定了该对象的哪些员是可见的。即使静态类型与动态类型可能不一致(当使用基类的引用或指针时会发生这种情况),但是我们能使用哪些成员仍然是由静态类型决定的。
举个例子,我们可以给Disc_quote 添加一个新成员
class Dise_quote ; public Quote f
publ1c:
void discount_policy() const
{}
// 其他成员与之前的版本一致
};
我们只能通过Disc_quote及其派生类的对象、引用或指针使用discount_policy
Bulk_quote bulk;
Bulk_quote *bulkP = &bulk; // 静态类型与动态类型一致
Quote *itemp = bulk; //静态类型与动态类型不一致
bulkp->discount_policy(); // 正确:bulkP的类型是 Bulk_quote*
itemP->discount policy() ; //错误:itemP的类型是Quote*
<