- 继承中的类作用域
类会创建一个命名空间,当继承的时候,子类的命名空间嵌套在父类的命名空间之中。- 这样,子类对象或者子类对象的指针或者引用 去查找一个元素的时候,可以在子类和父类的命名空间中去寻找。当然,优先找子类的命名空间。当子类的命名空间中找不到的时候,就去父类的命名空间中找。
- 如果一个指针或者引用是一个父类对象的,那么寻找的顺序就是从父类的命名空间开始找。即使实际的对象包含子类的命名空间,因为命名空间的特性,是找不到子类命名空间中的内容的。
- 也是因为这样的机制,子类可以使用和父类命名空间中相同名字的成员。子类中的名字会覆盖掉父类中的名字。
在不同作用域中的同名函数不会有重载的机制。也就是说,其不会智能地选择在外层作用域中同名,而且参数符合地函数。如果内层有符合名字地函数,那么直接调用。 - 覆盖:当父类中声明了一个虚函数,而子类中定义了一个同名,同参 的函数。那么当使用子类的指针或者引用或者对象调用这个函数的时候,调用的就是子类的函数。如果使用父类的指针或者引用来调用 子类对象中的这个函数的时候,调用的还是子类的函数。这就形成了一种覆盖。原来的父类的函数 找不到了 .
- 隐藏:当父类中的函数和子类中的函数是同名的时候,(不构成虚函数的覆盖关系,也就是可以是虚函数,但是不同参。也可以不是虚函数),如果从子类作用域开始查,就调用子类的函数。如果从父类的作用域开始查就调用父类的函数。这叫做隐藏。
- 多重继承问题:
- 多重继承意味着一个对象同时属于多个类的具体化,这是完全可能发生的。因为一个事物往往是有多个属性的。
- 多重继承可以理解为多个单继承。但是各个独立的单继承中间的子类部分是共有的,尽管在逻辑图上是不容易看出来的。
- 多重继承可能会有二义性问题。因为按照上述的查找规则,对于一个成员的查找(假设是一个子类的引用或者指针),我们按照继承树从下到上去查找。因为有两个父节点,因此,两路是同时进行的。如果在两路中发现了同一个名字符合的成员,也不去管是不是类型符合,那么就产生二义性错误,就报错。 如果不使用虚基类,并且两条路径包含同一个间接基类,那么就一定会报二义性错误。这种情况可以使用虚继承 来解决。
解决二义性的措施可以在调用的时候加上作用域限定符:: 或者在可能引发二义性的函数,在子类中重写。
- 虚继承:
- 虚继承只是声明虚基类(继承的时候使用virtual修饰的类)在将来的继承中,如果遇到相同的基类,那么可以共享,只保留一个版本。
- 虚基类除了改变内存情况,对于继承关系来说没有什么改变。