zoukankan      html  css  js  c++  java
  • 多继承引起的二义性

      多重继承可以反映现实生活中的实际情况,能有有效的处理一些较复杂的问题,使编程具有灵活性。但是多重继承也引起了一些值得注意的问题,它增加了程序的复杂度,使程序的编写和维护变得相当困难。其中最常见的问题就是继承成员同名而产生的二义性(Ambiguous)问题。

    ①调用不同基类的同名成员时可能出现二义性

     1 class A
     2 {
     3     public:
     4         void setA(int a);
     5         int get();
     6     private:
     7         int a;
     8 } ;
     9 class B
    10 {
    11     public:
    12         void setB(int b);
    13         int get();
    14     private:
    15         int b;
    16 } ;
    17 
    18 class C:public A,public B
    19 {
    20     public:
    21         void setC(int c);
    22         int getC();
    23     private:
    24         int c;
    25 };

      在执行obj.get();时将是有二义性的。因为类C分别从类A类B继承了两个不同版本的get()成员函数,因此,obj.get();到底调用哪个get()版本,编译器将无从知晓。

    对于这种二义性问题,常见有两种解决方法:

    (1)使用作用域分辨符::加以消除。

    obj.A::get();

    obj.B::get();

    (2)在类C中也定义成员函数get()函数,则有类C的对象obj访问get()函数obj.get()没有二义性,这是因为当派生类中的成员与基类中的成员重名时,派生类中的同名成员将被调用。

     1 class A
     2 {
     3     public:
     4         void setA(int a);
     5         int get();
     6     private:
     7         int a;
     8 } ;
     9 class B
    10 {
    11     public:
    12         void setB(int b);
    13         int get();
    14     private:
    15         int b;
    16 } ;
    17 
    18 class C:public A,public B
    19 {
    20     public:
    21         void setC(int c);
    22         int get();
    23                 //此处改为这样    
    24     private:
    25         int c;
    26 };

    ②访问共同基类的成员时可能出现二义性

      当一个派生类有多个基类,而这些基类又有一个共同的基类时,也就是所谓的菱形继承。这时对这个共同基类中成员的访问可能出现二义性。

     1 class A
     2 {
     3     public:
     4         void disp(); 
     5     private:
     6         int a;
     7 };
     8 
     9 class B1:public A
    10 {
    11     public:
    12         void dispB1();
    13     private: 
    14         int b1;
    15 };
    16 class B2:public A
    17 {
    18     public:
    19         void dispB2();
    20     private: 
    21         int b2;
    22 };
    23 
    24 class C:public B1,public B2
    25 {
    26     public:
    27         void dispC();
    28     private: 
    29         int c;
    30 };

    在此类结构下,如果创建类C的对象c1:

    C c1;

    则下面的两个访问都有二义性:

    c1.disp();

    c1.A::disp();

      这是因为B1,B2分别从类A中继承了一个disp()成员函数的副本,因此类C中就有了分别从类B1,B2两条不同路线上继承过来的disp()版本,尽管这两个版本的函数完全相同,但是语句“c1.disp();”将使编译器无从知晓到底调用从类B1继承来的disp(),还是调用从类B2继承来的disp(),这就是导致二义性的原因。

    语句“c1.A::disp();”产生二义性的道理相同,不过下面的两条调用语句却是正确的:

    c1.B1::disp();

    c1.B2::disp();

    因为通过“B1::”及“B2::”的限定,明确告诉编译器应该调用从哪条路径上继承过来的disp()。

      在一个类中保留间接共同基类 的多份同名成员,虽然有时是必要的,可以在不同的数据成员中分别存放不同的数据,也可以通过构造函数分别对它们进行初始化。但在大多数情况下,这种现象是人们不希望出现的。

    因为保留多份数据成员的副本,不仅占用较多的存储空间,还增加了访问这些成员时的困难。而且在实际上,并不需要有多份副本,为此,c++中提供了虚基类(Virtual Base Class)技术来解决这个问题。

    关于虚基类方面的内容请跳转至http://www.cnblogs.com/tenjl-exv/p/7625836.html

  • 相关阅读:
    [calss*="col-"]匹配类名中包含col-的类名,^以col-开头,$以col-结尾
    插件写法之脚本运行环境,mac和window检测
    @media only screen and (max-width:640px)中的问题,响应式布局
    webpack2的配置属性说明entry,output,state,plugins,node,module,context
    npm ERR! missing script: dev 报错解决
    [jshint] 'import' is only available in ES6 (use 'esversion: 6'). (W119) 提示import等ES6语法的jshint错误的,在代码前加一行 /* jshint esversion: 6 */
    Uncaught TypeError: (intermediate value)(...) is not a function 上一个方法结束没有加分号; 代码解析报错
    LeetCode 1. two sum
    redis集群尝试
    服务器搭建私人Git
  • 原文地址:https://www.cnblogs.com/tenjl-exv/p/7625484.html
Copyright © 2011-2022 走看看