请教有C++大型程序程序设计经验的大侠关于类层次结构的设计问题

6048475 2007-07-19 05:15:54
一个大型的程序,顶层有一个基类A,有很多个层次的A的子类B,C,D,E...。原来的A里面有许多类似于如下类型的纯虚函数:
virtual B* Fun1()=0;
virtual C* Fun2()=0;
这就导致了一个问题,在A的声明部分必须include所有这些子类的头文件,请问如何克服这个问题,可以不用包括这些子类的头文件,因为这样耦合性太强了。另外请注意Fun1和Fun2在很多个子类中都得到了实现,所以原来的设计将其放于基类中似乎也不无道理,只是觉得不优雅。
...全文
294 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
superarhow 2007-07-20
  • 打赏
  • 举报
回复
virtual B* GetB() = 0;
如果偶来做的话偶还是会做成virtual A* GetB() = 0;
而在调用端将它dynamic_cast成B。至少Office,IE的DOM类都是这样做的。虽然GetApplication()返回的是IApplication,但仍然使用IUnknown来传递这个指针。
6048475 2007-07-20
  • 打赏
  • 举报
回复
abfahren2000兄,我之所以在这里问就因为觉得这种设计的格局不太优雅,但是此程序正常运行是没有问题的,正因为儿子没生出来,所以才用的纯虚函数,并且仅仅返回指针,纯粹只是接口的描述,没有什么问题。只想让程序优雅一点,大家继续讨论吧,呵呵!
Vitin 2007-07-20
  • 打赏
  • 举报
回复
要降耦可以参考《设计模式》,其中很多是以降耦为目标的。

比如可以参考Mediator的设计精神,设计一个新类DownCastForA 完成A向其派生类的转化。它可以提供函数B* Fun1(A*)、C* Fun2(A*)等,内部使用dynamic_cast做转换,也可先用RTTI做检查。
6048475 2007-07-20
  • 打赏
  • 举报
回复
这是国外的一个很大的软件的设计,大约有几百个类,既然讨论的差不多了,结贴了,呵呵!感谢taodm和superarhow的提醒,也感谢大家参与!
abfahren2000 2007-07-20
  • 打赏
  • 举报
回复
"对于那个父类,儿子都还没生出来,都把儿子给用上了啊。"
顶这句!小弟以为这个设计在逻辑上就有问题!
前置声明,治标不治本!
houdy 2007-07-20
  • 打赏
  • 举报
回复
virtual B* Func1() = 0;
----------
晕,这里写错了。应该是:
virtual A* Func1() = 0;
jxlczjp77 2007-07-20
  • 打赏
  • 举报
回复
houdy(致力于图像/图形领域,成为有思想的程序员) 讲的没错,何必要返回子类的指针,定义一个基类,不就是想用基类的借口来使用所有的子类吗,你这样的设计逻辑应该有问题
6048475 2007-07-20
  • 打赏
  • 举报
回复
superarhow的意见非常好,看来我书读死了,没想到这一层,大家继续,可惜没办法给帖子加分提高赏金,抱歉!
krfstudio 2007-07-20
  • 打赏
  • 举报
回复
同意楼上的。
6048475 2007-07-19
  • 打赏
  • 举报
回复
《Excetpional C++》真有吗,我找找看,这本书买了没怎么看。前置声明确实有效,但是就是觉得还是耦合的比较紧。希望大家继续讨论,看能不能碰撞出什么新点子来呢,我觉得这类问题还是蛮有价值的,呵呵!
星羽 2007-07-19
  • 打赏
  • 举报
回复
只是指针的话,不用include .h 只要声明一下就可以了

比如


class B;
class C;

virtual B* Fun1()=0;
virtual C* Fun2()=0;
KenYuan2016 2007-07-19
  • 打赏
  • 举报
回复
把class 全部先生命在A中,就不需要头文件了,
不过还是很烂。

耦合度这么高。

对了,java里面的类都基于object, java又是怎么实现的?

耦合度太高,到时候维护起来就很费尽,增加功能时更麻烦。
Inhibitory 2007-07-19
  • 打赏
  • 举报
回复
对于那个父类,儿子都还没生出来,都把儿子给用上了啊。
houdy 2007-07-19
  • 打赏
  • 举报
回复
一些建议:
1.如果类的层次以及派生类比较多的情况,可以分层并且使用组合的方式。
2.可以考虑这样的虚函数:
2.1 在基类A中声明这样的虚函数:
virtual A* Func1() = 0;
2.2 在派生类B中声明这样的虚函数:
virtual B* Func1() = 0;
(注:这样的函数虚函数声明是允许的,只要保证B是A的派生类)
另外,使用前项声明也不失是一个好的方法。
MPTD_Fire 2007-07-19
  • 打赏
  • 举报
回复
up
jixingzhong 2007-07-19
  • 打赏
  • 举报
回复
一样

和纯虚没有关系。
只要你不需要访问 B 的细节即可。
jixingzhong 2007-07-19
  • 打赏
  • 举报
回复
virtual B* Fun1()=0;

定义 B* 返回,
前置声明足以。

class B; //不需要 #include<B.h>了
virtual B* Fun1()=0;
nnull 2007-07-19
  • 打赏
  • 举报
回复
不用纯虚的呢?
jixingzhong 2007-07-19
  • 打赏
  • 举报
回复
这个需要实践、时间
taodm 2007-07-19
  • 打赏
  • 举报
回复
用类的前置声明啊。
在class A前面加class B;class C;。。。
建议看《Excetpional C++》有这个解耦问题的解答。

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧