自己封装常用代码时所面临的困境(一起来讨论怎么构建个人c++库)
自己封装常用代码时所面临的困境(一起来讨论如何构建个人c++库)
本人工作近1年了,目前只负责过一些简单的设备接口的封装,都很简单,没什么技术含量。时间久了,发现自己做的很多事都是重复的,所以打算自己封装一个个人库。着手开始做的时候,才感觉心有余而力不足。
我的理念是,尽可能把库写地精巧,进行浅层次封装,但又要方便自己使用。如果能不引入c++类的地方就不引入类。但是,我发现自己对类的依赖性太强了,写下面一个简单的函数时就不知道怎么办了:
这个函数的目的是:把文件数据一次性加载到内存中。
调用方式是:返回值说返回的是错误信息,byte* buffer 是出参,用户只要提供文件路径FileName、有效字节偏移量offset、文件类型标签FTTag,和一个用于获得数据的buffer就行了。
说到这里,一定会有前辈批评我为什么要在函数内部对buffer进行堆内存分配。这就是问题的开始了。
我之所以这样做,是因为我希望分配和文件大小一致的buffer。如果放在外面分配内存,我就无从得到这个文件大小了,如果说要我定义一个全局变量,来存储filesize,那样做的话,和没有封装就没什么两样了。 当然,如果使用类的话,这个问题可以很容易解决。问题是我前面说了,不希望引入类和继承之类的降低性能的机制,我只打算建立一个小型易用的库。
请问各位前辈有什么好的建议?
另外,内存分配是不是最好要遵循谁使用谁释放的原则?
最近很少回帖,都没可用分了,后面我会追加分数!
------解决方案--------------------
>不希望引入类和继承之类的降低性能的机制
class甚至继承对性能不是没有任何影响,就是小到几乎任何状况都可以忽略
你所谓的开销主要是来自virtual
利用class进行浅封装不会对性能构成影响的
------解决方案--------------------
我的看法是,只要不过多的使用类的继承和多态,为什么不用类的方式呢?类本来就是封装的好手。
个人建议,建立你的几个基本类,然后以这些基本类为基础,去增加你的扩展工具类。注意,这里以基本类为基础,不是说从它们派生,而是将这些基本类作为工具,尽量做到之间的耦合只限于基本类的对象或指针,这样或者是一个累积个人类库的方法。
另,内存分配建议最好是谁申请谁释放。你的例子中,为什么不用智能指针呢?
------解决方案--------------------
你用不用class跟你的性能高不高没有绝对的关系
既然要用c++开发高性能的库
花时间搞懂c++的有的那些抽象机制
需要付出那一些代价是很值得的
要讲的东西太多,我觉得你还是直接去读一读c++ primer 5好了
然后是effective c++, more effective c++
及exceptional c++.觉得太多书要读可以直接看
C++ Coding Standards: 101 Rules, Guidelines, and Best Practices
c++提供的抽象机制不是全部都要付出执行时间的代价的
如果要用smart pointer,可以优先考虑unique_ptr
shared_ptr可以等你有必要使用的时候再用
觉得自己功力还不错的话可以挑战一下及inside the c++ object model
如果觉得要读这么多书很烦,不想花时间学习
直接用c就好了,c++的学习时间确实比较漫长
------解决方案--------------------
如果不嫌累的话,effective stl也可以看一看
题外话,我从来没看过有那个c++的大牛大力推荐
大家大量使用继承的,反倒是看过herb,meyers,
bjarne等人建议大家不要经常使用继承
但是现实社会的例子是举凡支援oo的语言
一定到处都是继承,不管有没有继承的必要
我就是要继承,这真是一个无比诡异的现象
------解决方案--------------------
返回 vector<unsigned char>不好么
------解决方案--------------------
继承是OO的基础设施,如果没有继承,就无法实现多态性,而多态性是OO的手段。所以任何讲OO的文章,都会涉及继承。不要从字面或语法角度看“避免使用继承”这个忠告,而应该从设计的角度出发来看。
Andrei Alexandrescu说“设计就是做选择“。设计模式研究OOP类体系之间的关系和方法,它的两个基本手段是继承和合成。前者属于静态设计方式,在类级别上复用代码,在编译期决定设计。后者属于动态设计方法,在类对象级别上复用代码,在运行期灵活切换。不同的设计模式选择不同的方式或两者的结合来解决模块的表示、交互问题。满足现代软件开发的各种需求。
但就算是采用组合方式来构建系统,为了进行恰当的运行时功能切换,也需要让组合对象有一个多态性体系,否则你无法保持接口的一致性。这还是基于继承的——至少你的组合对象体系必须是多态的。所以OOP离不开继承,因为它是基础。
------解决方案--------------------
本人工作近1年了,目前只负责过一些简单的设备接口的封装,都很简单,没什么技术含量。时间久了,发现自己做的很多事都是重复的,所以打算自己封装一个个人库。着手开始做的时候,才感觉心有余而力不足。
我的理念是,尽可能把库写地精巧,进行浅层次封装,但又要方便自己使用。如果能不引入c++类的地方就不引入类。但是,我发现自己对类的依赖性太强了,写下面一个简单的函数时就不知道怎么办了:
#define EG_DLL_EXPORT
#include"FileIO.h"
int EG::LoadToBuffer(const char* FileName,int offset,TagType FTTag,byte* buffer)
{
FILE* f=fopen(FileName,"rb");
if(!f)
return FAILED_TO_OPEN; //文件打开失败
fseek(f,offset,SEEK_CUR);
TagType Tag;
fread(&Tag,sizeof(TagType),1,f);
if(Tag!=FTTag)
return INVALID_DATATYPE; //文件类型不正确
int fileSize=_filelength(_fileno(f))-offset;
buffer=new byte[fileSize];
fread(buffer,fileSize,1,f);
fclose(f);
return OK;
}
这个函数的目的是:把文件数据一次性加载到内存中。
调用方式是:返回值说返回的是错误信息,byte* buffer 是出参,用户只要提供文件路径FileName、有效字节偏移量offset、文件类型标签FTTag,和一个用于获得数据的buffer就行了。
说到这里,一定会有前辈批评我为什么要在函数内部对buffer进行堆内存分配。这就是问题的开始了。
我之所以这样做,是因为我希望分配和文件大小一致的buffer。如果放在外面分配内存,我就无从得到这个文件大小了,如果说要我定义一个全局变量,来存储filesize,那样做的话,和没有封装就没什么两样了。 当然,如果使用类的话,这个问题可以很容易解决。问题是我前面说了,不希望引入类和继承之类的降低性能的机制,我只打算建立一个小型易用的库。
请问各位前辈有什么好的建议?
另外,内存分配是不是最好要遵循谁使用谁释放的原则?
最近很少回帖,都没可用分了,后面我会追加分数!
私人库
dll
------解决方案--------------------
>不希望引入类和继承之类的降低性能的机制
class甚至继承对性能不是没有任何影响,就是小到几乎任何状况都可以忽略
你所谓的开销主要是来自virtual
利用class进行浅封装不会对性能构成影响的
------解决方案--------------------
我的看法是,只要不过多的使用类的继承和多态,为什么不用类的方式呢?类本来就是封装的好手。
个人建议,建立你的几个基本类,然后以这些基本类为基础,去增加你的扩展工具类。注意,这里以基本类为基础,不是说从它们派生,而是将这些基本类作为工具,尽量做到之间的耦合只限于基本类的对象或指针,这样或者是一个累积个人类库的方法。
另,内存分配建议最好是谁申请谁释放。你的例子中,为什么不用智能指针呢?
------解决方案--------------------
你用不用class跟你的性能高不高没有绝对的关系
既然要用c++开发高性能的库
花时间搞懂c++的有的那些抽象机制
需要付出那一些代价是很值得的
要讲的东西太多,我觉得你还是直接去读一读c++ primer 5好了
然后是effective c++, more effective c++
及exceptional c++.觉得太多书要读可以直接看
C++ Coding Standards: 101 Rules, Guidelines, and Best Practices
c++提供的抽象机制不是全部都要付出执行时间的代价的
如果要用smart pointer,可以优先考虑unique_ptr
shared_ptr可以等你有必要使用的时候再用
觉得自己功力还不错的话可以挑战一下及inside the c++ object model
如果觉得要读这么多书很烦,不想花时间学习
直接用c就好了,c++的学习时间确实比较漫长
------解决方案--------------------
如果不嫌累的话,effective stl也可以看一看
题外话,我从来没看过有那个c++的大牛大力推荐
大家大量使用继承的,反倒是看过herb,meyers,
bjarne等人建议大家不要经常使用继承
但是现实社会的例子是举凡支援oo的语言
一定到处都是继承,不管有没有继承的必要
我就是要继承,这真是一个无比诡异的现象
------解决方案--------------------
返回 vector<unsigned char>不好么
------解决方案--------------------
继承是OO的基础设施,如果没有继承,就无法实现多态性,而多态性是OO的手段。所以任何讲OO的文章,都会涉及继承。不要从字面或语法角度看“避免使用继承”这个忠告,而应该从设计的角度出发来看。
Andrei Alexandrescu说“设计就是做选择“。设计模式研究OOP类体系之间的关系和方法,它的两个基本手段是继承和合成。前者属于静态设计方式,在类级别上复用代码,在编译期决定设计。后者属于动态设计方法,在类对象级别上复用代码,在运行期灵活切换。不同的设计模式选择不同的方式或两者的结合来解决模块的表示、交互问题。满足现代软件开发的各种需求。
但就算是采用组合方式来构建系统,为了进行恰当的运行时功能切换,也需要让组合对象有一个多态性体系,否则你无法保持接口的一致性。这还是基于继承的——至少你的组合对象体系必须是多态的。所以OOP离不开继承,因为它是基础。
------解决方案--------------------