C++中的多重继承

原创 2004年06月25日 15:51:00

C++中的多重继承<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

虽然在软件设计中,许多书籍都推荐优先使用组合而不是继承,然而继承仍然拥有许多天然的优势,对基类成员的自动拥有,而不用像组合要显示地去转向调用所需复用的成员,从而平添更多的代码。

多重继承在某些情况下,可以使我们的设计具有更多的灵活性,下面我们讨论一些多重继承中的问题及解决办法。

 

我们实现了一个抽象基类A,然后由此派生了出了诸多的实现类,如A1,A2,A3,在项目的起初,这些A的具体类工作很好,我们的软件模块也依赖于这一个抽象基类A。一切都很好。随着项目的进行。我们又进入了另一个模块的开发。也许起先的考虑不周,也许设计师在设计时出现了其他什么,这里我们又要使用这些A1A2A3了。但是我们也发现,抽象基类A的这些接口方法已经不能满足这一个模块的功能要求了,在这个新的模块中,我们需要另一些通用的方法干其它的一些事情。怎么办?我们要重写A1A2A3,并且加入在新模块中所需要的这些通用的方法吗?但是根据软件开发的接口依赖原则,我们的软件模块还能够依赖于抽象基类A?可是这些新增的通用方法并未在A中声明。或许我们应该考虑一下多重继承,将新增的通用方法抽象到一个新的接口B中。这样我们在使用A1的新增方法时,只需依赖于这个新的接口B,而在使用A1以前的方法时,只需依赖于接口A

真是个好主意。于是新的派生类实现了。A11继承于A1BA22继承于A2BA33继承于A3B,应用环境如下:

 

bool App::AddSub(B* b)

{

       A* a = dynamic_cast<A*>(b);     //动态转换为A;

 

       If (a!=0)

       a->MethodA();

else

       return false //转换出错,输入参数不是我们期望的类型;

 

b->MethodB(); //调用接口B中的方法;

 

return true;

}

 

可以看到,软件模块依赖于一个接口B,同时还要验证其是否继承自A,否则便不是该模块所需的类型。

该模块可以很好地运行。但注意上面对类型A的转换是通过动态类型转换来实现的。而其具体的实现依赖于RTTI,而在某些情况下,我们不能应用RTTI机制。如果我们关掉编译器的RTTI选项。上面的代码可能就不能正确运行了。怎么办呢?如果我们知道多重继承的机制,这或许可以帮助我们解决这个问题。可以参考C++编程思想或深度探索C++对象模型的相关章节。

下面是一种解决方法。

我们在B中增加一个多态的virtual void* GetThis()方法用以返回this指针,并在A11A22A33中都有它的实现,在应用环境中:

 

bool App::AddSub(B* b)

{

       A* a = static_cast<A*>(b->GetThis());             

a->MethodA(); //调用接口A中的方法;

b->MethodB(); //调用接口B中的方法;

 

return true;

}

 

上面的实现中通过多态的GetThis()方法,获得具体实现类的指针并转换为A,但是由于编译器关闭了对RTTI的支持,这种转换并非类型安全,需要事先约定传入类型包括了对AB的实现,否则转换将不能达到我们期望的效果。

 

C++中的#,##,和"

想要灵活应用宏,离不开#和##。 " 在学习#和##之前,先来看一个关于"的例子: #include #include int main() { const char* p1 = ...
  • mzlogin
  • mzlogin
  • 2014年11月09日 22:47
  • 7584

C++中的::的作用

(1)作用域限定符,当在类体中直接定义函数时,不需要在函数名字的前面加上类名,但是在类体外实现函数定义的时候,必须加上类名并且加上作用域限定符。Student::Display(); (2)...
  • zhanghuaichao
  • zhanghuaichao
  • 2017年02月18日 21:44
  • 2253

浅论C++的复杂性

C++语言已经有了20多年的历史。作为一门影响广泛的编程语言,它所受到的关注和争论恐怕是任何一门其他的语言所不能比拟的。十几年前,Java等新生语言的出现曾导致“C++信任危机”,但最终C++以自身非...
  • K346K346
  • K346K346
  • 2015年12月05日 11:56
  • 1738

C++笔试题目大全(笔试宝典)(不断完善中)

1.new 、 delete 、 malloc 、 free 关系 delete 会调用对象的析构函数 , 和 new 对应 free 只会释放内存, new 调用构造函数。 malloc 与 f...
  • Lina_ACM
  • Lina_ACM
  • 2016年06月07日 13:29
  • 21413

c/c++中指针的理解(初学者)

关于指针,大家肯定不陌生,一些初学者,想必会出现思绪混乱的情况,现在我就来帮大家缕一缕吧。(第一次写微博 有点小紧张) 大家应该了解一些计算机对内存的管理方式吧。操作系统会将内存单元进行编号,这些...
  • Allen_ww
  • Allen_ww
  • 2016年01月11日 19:41
  • 8781

没事写点啥(一)——C++扫雷

整天编学校的作业实在枯燥,不如……写点别的?
  • destinyson
  • destinyson
  • 2016年02月29日 14:17
  • 1762

C/C++中“#”和“##”的作用和用法

C/C++中“#”和“##”的作用和用法!
  • fengbingchun
  • fengbingchun
  • 2015年03月08日 16:15
  • 3385

C++ 进程间的通讯(一):简单的有名管道实现

进程间的通讯(一):简单的有名管道实现 一 管道简介 命名管道(Named Pipe)是服务器进程和一个或多个客户进程之间通信的单向或双向管道。不同于匿名管道的是命名管道可以在不相关的进程...
  • u010797208
  • u010797208
  • 2014年11月28日 02:09
  • 6574

OpenCV中Mat的C++用法介绍

Mat       OpenCV 自 2001 年出现以来。在那些日子里库是围绕C接口构建的。在那些日子里,他们使用名为IplImage C 的结构在内存中存储图像。这是您将在大多数较旧的教程和...
  • wadefan7
  • wadefan7
  • 2015年03月05日 15:53
  • 4293

关于C和C++一些大神们的讨论

知乎上曾经有一个关于C和C++语言的讨论,弄的沸沸扬扬。余天升 开源社区一直都不怎么待见C++,自由软件基金会创始人Richard Stallman认为C++有语法歧义,这样子没有必要、非常琐碎还会...
  • wangshubo1989
  • wangshubo1989
  • 2016年02月23日 20:33
  • 2637
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中的多重继承
举报原因:
原因补充:

(最多只允许输入30个字)