我更喜欢朴素的C式的C++,而不是java式的C++

蓝鹰 2013-04-04 06:16:04
加精
最近在给公司做一套3D字体渲染类。其中遇到了如何避免向用户暴露第三方类型声明的问题。

//textRenderable.h:
//textRenderable.dll接口
class DLL_API CTextLatticeCacheMgr //点阵缓存管理类
{
A *m_pA; //其中A 是第三方的字体文件解析引擎
//......
void generateFontLattice(wchar_t uch); //生成unicode字符的点阵坐标函数
}

//textRenderable.cpp:
#include "ThirdHeader.h"
#include "textRenderable.h"
void CTextLatticeCacheMgr::generateFontLattice(wchar_t uch)
{
AInit(m_pA);
//......
}
}




如果用户想使用textRenderable.dll,我不仅得提供textRenderable.h ,还必须提供ThirdHeader.h
这样就会暴露一些不必要暴露的第三方软件细节。老大给我的建议是用前置声明,和动态创建类,大概意思就是写个类B把A包起来,在构造函数里面new 一个A,然后 把B 放在CTextLatticeCacheMgr 进行前置声明。 这种写法很普遍,但是我很少用过,毕竟在工作中使用C++ 还不到半年。不过,我现在真的厌倦了 一层又一层的封装抽象,况且CTextLatticeCacheMgr 这个类 对效率要求也很敏感。 不是担心我代码的效率吗? 现在又要我做这事,而且系统不加字体本身的帧率就低得吓人。 于是我就没听老大的。就简单地把代码写成这样

//textRenderable.h:
//textRenderable.dll接口
class DLL_API CTextLatticeCacheMgr //点阵缓存管理类
{
void *m_pA; //把原本的A* 改为void *
//......
void generateFontLattice(wchar_t uch); //生成unicode字符的点阵坐标函数
}

//textRenderable.cpp:
#include "ThirdHeader.h"
#include "textRenderable.h"
void CTextLatticeCacheMgr::generateFontLattice(wchar_t uch)
{
AInit((A*)m_pA); //强制类型转换,哈哈,这样不就避免了向用户暴露不必要的细节了吗?
//......
}
}


自从做了C++ ,我就厌倦了 一层又一层的封装抽象。有时候真的怀疑:这些复杂的层次真的有助于维护和扩展吗? 我想,有时候,对于一些简单的问题,我们真该返璞归真,使用C的朴实的表达方式。 将毫不相干的代码堆叠在一起的编码风格固然恶劣,过分细致地封装和抽象,满眼尽是接口的互相调用,一些关联性极强的实现被拆得七零八落不一样另人懊恼? 难道不是吗? 为什么人们最终没使用ISO的 七层网络结构而 把它精简为5层,我想就是这个道理
...全文
27036 228 打赏 收藏 转发到动态 举报
写回复
用AI写文章
228 条回复
切换为时间正序
请发表友善的回复…
发表回复
abingzjmzjm 2013-10-12
  • 打赏
  • 举报
回复
忽略其他因素的话,非常赞成返朴归真的思想
hu7324829 2013-09-24
  • 打赏
  • 举报
回复
如果没有virtual函数,virtual继承,多重继承, 编译器对class的行为就相当于struct, 再加上inline, c++的效率基本和C不相上下了,
adfaksdf 2013-09-24
  • 打赏
  • 举报
回复
引用 35 楼 ayrb13 的回复:
[quote=引用 30 楼 blackeagleX 的回复:] 引用 24 楼 ayrb13 的回复:有些不懂呀,你的成员变量只是一个指针,完全可以这么写 C/C++ code?123456789101112131415161718//textRenderable.h://textRenderable.dll接口class A;class DLL_API CTextLatticeCacheMgr //点阵缓存管理类{ ……
如果是A类型的成员变量,那么前置声明类会编译错误,因为编译器不知道该为CTextLatticeCacheMgr类型变量分配多少内存空间,但是指针的内存空间是确定的,32位环境下都是4字节。 现在公司项目里编译的静态库与动态库大量用到前置声明,用指针作为成员变量也是一种解耦的方法。 不知道为什么你说会编译错误。。请贴出你的代码例子和编译器输出错误吧。[/quote] 对啊,我也感觉不会有编译错误的吧。
追求执着 2013-05-03
  • 打赏
  • 举报
回复
简单才是硬道理!
blueWaterSky 2013-05-03
  • 打赏
  • 举报
回复
真正的高手做什么东西没有什么具体的形式,软件开发中具体的时间通常要和业务、需求,未来的扩展等结合在一起考虑: 1、如果系统只是个小工具,未来不用扩展,那些架构、面向对象的思想就是杀鸡用牛刀; 2、如果系统需求非常稳定,在系统设计上可能不用过多考虑复杂的设计模式应用,那样反而会带来很多不便;可能基本类库 + 业务类库 + (数据类库 +) UI层,各自独立,也不失为一种很好的方式 3、如果业务和需求需要,则采用成熟的设计模式会更好。 总的来说,应用和需求决定一切。 举个小例子,微软提供的petshop中采用factory模型来支持多个数据库,当然不错,但下面的方式是否可行?不用设计模式,而是对不同的数据库写一个project,不同的数据库访问和操作用不同的project去做就行了,这样,由于模型更简单,开发人员只需要关心每个porject的不同数据访问代码实现即可,也未尝不是一种解决的方法。
赵4老师 2013-05-02
  • 打赏
  • 举报
回复
尺有所短,寸有所长。
fthislife 2013-05-02
  • 打赏
  • 举报
回复
引用 100 楼 weiym 的回复:
C++支持多种范型,因此代码风格不像C#/Java那样只有一种长相。 经过多年实践,个人现在比较支持这种风格: (1)底层语言基础库(STL, Boost)以泛型主导,应用基础库(如Factory, Singleton)也可以适当使用泛型。基础库可以以traits,policy的方式进行精致的设计, 以模板参数的方式考虑所有的可变情况(Looki),以通用和高效为基本原则。 (2)中间应用层以模式和面向对象为主导, 应用层逻辑也是多变的, 理论上也可采用模板的的方式来应对变化。但是应用层的变化往往是非常复杂的, 甚至是不可预测的, 所以你不可能以泛型的方式预测到所有的变化。C++现在还没有对泛型的concepts的描述机制,导致模板代码比较难懂。在多变的应用逻辑层大量采用模板显然不是一个好的选择。另外,模板在应用层的大量使用也没有比较成熟的经验,而面向对象和模式则已是非常成熟。中间层以能灵活应对变化为设计原则。 (3)模块(dll)间的交互则是以C方式的API 或者 仿COM(Factory+Interface) 为主导, 这些用法都已经非常成熟。模块接口层以二进制兼容为设计原则。
++
  • 打赏
  • 举报
回复
在比较大的项目中,如果没有用好封装,对后期维护、重用及维护来说是个灾难,甚至可能到了没有维护的必要,可以直接扔了。乱用封装,也会让后来人员看的一头雾水,本来关联性很好的几个东西,偏偏给封装了起来,让人不能直接明白他们之间的关联性。总之,只要坚持封装是为了模块化,容易理解,一般来说没有固定的模式。
u010237024 2013-04-29
  • 打赏
  • 举报
回复
it小白到此一游 饱含各位大神精髓
backo880607 2013-04-29
  • 打赏
  • 举报
回复
楼主应该去了解下插件,你完全可以把这些功能封装到插件DLL中,而外界只需一个接口文件,完全不需你那个第三方头文件。如果去了解插件是如何实现的话,你会感受到其强大的魅力,如果要我去喜欢C++的话,我喜欢的理由是:完全控制,无论是从代码质量,设计,架构等等,而且C++可以帮助你去实现一些奇思妙想……所以我倒觉得喜欢研究的人可能会喜欢C++。
RichardQF 2013-04-29
  • 打赏
  • 举报
回复
引用 238 楼 richardcheng1971 的回复:
楼主是没有理解面向对象语言的真正作用,封装、多态和继承是C++的精髓,真正按照面向对象思想设计的软件系统具有很强的设计弹性,可以减少后期的维护工作工作量,这是C语言不具备的。 建议楼主看看《C++大规模软件系统设计》一书,里边介绍很多大规模C++的设计技巧。
书名写错了,应该是《大规模C++程序设计》
RichardQF 2013-04-29
  • 打赏
  • 举报
回复
楼主是没有理解面向对象语言的真正作用,封装、多态和继承是C++的精髓,真正按照面向对象思想设计的软件系统具有很强的设计弹性,可以减少后期的维护工作工作量,这是C语言不具备的。 建议楼主看看《C++大规模软件系统设计》一书,里边介绍很多大规模C++的设计技巧。
Cofox2019 2013-04-29
  • 打赏
  • 举报
回复
如果多人多同一个项目,或者项目会延续1年甚至更长。那么封装是必要的,而且是非常必要的。
qiminixi 2013-04-28
  • 打赏
  • 举报
回复
COM、ATL和ActiveX就是通过层层封装建立的 按照老大的说法,将m_pA封装到类中,这样用户只剩下了使用引擎的分,即时引擎改变对用户的影响也会比较小。用户完全不用管引擎是如何打开、如果工作、如果关闭的。 ···翻页吧
sanhan 2013-04-28
  • 打赏
  • 举报
回复
呵呵。楼主这问题让我想起一个带过的工程师。 那个工程师写的程序很漂亮,左一个类右一层封装的,注释也相当完整。 问题是: 。。。他的工作永远完成不了,虽然整天加班。 后来,我和他一起审查代码,花了一个小时删掉了90%。 再后来,他离职了。 用C++的,如果不把C学透,还不如用Java。
蓝鹰 2013-04-28
  • 打赏
  • 举报
回复
引用 123 楼 BoweirrKing 的回复:
楼主你的这种做法,是有局限性的。通过转化为void*指针来传递对象,是不安全的。尤其是在复杂的多重继承类的应用中。 这样的的做法,有些时候在回复为对象指针时,会丢失指针本身的信息,造成程序崩溃退出。我曾经遇到过这类问题的。
谢谢提醒。我好像也遇到过类似的,不过不完全一样的问题。 但这里不要紧。就我的项目而言,void* 一般会指向一些很底层的结构,这些结构都是十分注重性能的,就像vector3 和 matrix4 这些类。这些类都不会用到虚函数甚至连继承都不会有
蓝鹰 2013-04-28
  • 打赏
  • 举报
回复
引用 231 楼 sanhan 的回复:
呵呵。楼主这问题让我想起一个带过的工程师。 那个工程师写的程序很漂亮,左一个类右一层封装的,注释也相当完整。 问题是: 。。。他的工作永远完成不了,虽然整天加班。 后来,我和他一起审查代码,花了一个小时删掉了90%。 再后来,他离职了。 用C++的,如果不把C学透,还不如用Java。
删了90%!那样写代码真是自己玩自己啊。 现在我的这个任务 历经半个月,完成了。谢谢大家!
蓝鹰 2013-04-28
  • 打赏
  • 举报
回复
引用 230 楼 xxxpriority 的回复:
楼主想多了,先做做吧
嗯,我在288楼已经承认了这一点。
x_jefferson 2013-04-28
  • 打赏
  • 举报
回复
楼主想多了,先做做吧
就是那个党伟 2013-04-27
  • 打赏
  • 举报
回复

printf("hello world")!
加载更多回复(208)

64,648

社区成员

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

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