我需要通过一个流来连接两个库.
QDataStream which is a stream from Qt
和另一个类似这样的库的一些功能
void read_something(istream& i);
我无法控制如何创建QDataStream,并且我不允许更改read_somthing函数的接口.
我可以想到的第一件事是写一个继承istream并包装QDataStream的类.有人做过吗?
如果我认为不是正确的方法,我想知道什么是最好的方式来实现.
解决方法
你应该做的是写一个streambuf,它使用QDataStream readBytes和writeBytes来实现它的功能.然后使用rdbuf将streambuf注册到一个istream中(您也可以在初始化时编写一个istream descendant).
Boost包含一个旨在促进streambuf写作的图书馆.使用它可能比理解streambuf界面更简单(个人我从来没有使用过,但我已经写了多个streambuf;我会看看我有一个例子,我可以发布).
编辑:这里是一些(用法语评论 – 来自法国的fr.comp.lang.c的常见问题解答,我没有时间翻译,认为最好离开他们,而不是删除它们)包装文件*调用streambuf.这也是使用私有继承的示例:确保在基类之前初始化什么可以是成员.在IOStream的情况下,基类也可以接收一个NULL指针,然后使用成员init()来设置streambuf.
#include <stdio.h> #include <assert.h> #include <iostream> #include <streambuf> // streambuf minimal encapsulant un FILE* // - utilise les tampons de FILE donc n'a pas de tampon interne en // sortie et a un tampon interne de taille 1 en entree car l'interface // de streambuf ne permet pas de faire moins; // - ne permet pas la mise en place d'un tampon // - une version plus complete devrait permettre d'acceder aux // informations d'erreur plus precises de FILE* et interfacer aussi // les autres possibilites de FILE* (entre autres synchroniser les // sungetc/sputbackc avec la possibilite correspondante de FILE*) class FILEbuf: public std::streambuf { public: explicit FILEbuf(FILE* cstream); // cstream doit etre non NULL. protected: std::streambuf* setbuf(char_type* s,std::streamsize n); int_type overflow(int_type c); int sync(); int_type underflow(); private: FILE* cstream_; char inputBuffer_[1]; }; FILEbuf::FILEbuf(FILE* cstream) : cstream_(cstream) { // le constructeur de streambuf equivaut a // setp(NULL,NULL); // setg(NULL,NULL,NULL); assert(cstream != NULL); } std::streambuf* FILEbuf::setbuf(char_type* s,std::streamsize n) { // ne fait rien,ce qui est autorise. Une version plus complete // devrait vraissemblablement utiliser setvbuf return NULL; } FILEbuf::int_type FILEbuf::overflow(int_type c) { if (traits_type::eq_int_type(c,traits_type::eof())) { // la norme ne le demande pas exactement,mais si on nous passe eof // la coutume est de faire la meme chose que sync() return (sync() == 0 ? traits_type::not_eof(c) : traits_type::eof()); } else { return ((fputc(c,cstream_) != EOF) ? traits_type::not_eof(c) : traits_type::eof()); } } int FILEbuf::sync() { return (fflush(cstream_) == 0 ? 0 : -1); } FILEbuf::int_type FILEbuf::underflow() { // Assurance contre des implementations pas strictement conformes a la // norme qui guaranti que le test est vrai. Cette guarantie n'existait // pas dans les IOStream classiques. if (gptr() == NULL || gptr() >= egptr()) { int gotted = fgetc(cstream_); if (gotted == EOF) { return traits_type::eof(); } else { *inputBuffer_ = gotted; setg(inputBuffer_,inputBuffer_,inputBuffer_+1); return traits_type::to_int_type(*inputBuffer_); } } else { return traits_type::to_int_type(*inputBuffer_); } } // ostream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf,ce qui permet de s'assurer // qu'il est bien initialise avant std::ostream class oFILEstream: private FILEbuf,public std::ostream { public: explicit oFILEstream(FILE* cstream); }; oFILEstream::oFILEstream(FILE* cstream) : FILEbuf(cstream),std::ostream(this) { } // istream minimal facilitant l'utilisation d'un FILEbuf // herite de maniere privee de FILEbuf,ce qui permet de s'assurer // qu'il est bien initialise avant std::istream class iFILEstream: private FILEbuf,public std::istream { public: explicit iFILEstream(FILE* cstream); }; iFILEstream::iFILEstream(FILE* cstream) : FILEbuf(cstream),std::istream(this) { } // petit programme de test #include <assert.h> int main(int argc,char* argv[]) { FILE* ocstream = fopen("result","w"); assert (ocstream != NULL); oFILEstream ocppstream(ocstream); ocppstream << "Du texte"; fprintf(ocstream," melange"); fclose(ocstream); FILE* icstream = fopen("result","r"); assert (icstream != NULL); iFILEstream icppstream(icstream); std::string word1; std::string word2; icppstream >> word1; icppstream >> word2; char buf[1024]; fgets(buf,1024,icstream); std::cout << "Got :" << word1 << ':' << word2 << ':' << buf << '\n'; }