我正在将 zip 和 rar 存档中的文件提取到原始缓冲区中。我创建了以下内容来包装 minizip 和 unrarlib:
Archive.hpp - 用于访问所有内容。如果我能让其他类中的所有函数都无法从外部访问,我会的。 (实际上,我想我可以将 Archive 中的所有其他类添加为好友并使用私有(private)函数回调...,但这太迂回了。)
#include "ArchiveBase.hpp"
#include "ArchiveDerived.hpp"
class Archive {
public:
Archive(string path) {
/* logic here to determine type */
switch(type) {
case RAR:
archive_ = new ArchiveRar(path);
break;
case ZIP:
archive_ = new ArchiveZip(path);
break;
case UNKNOWN_ARCHIVE:
throw;
break;
}
}
Archive(Archive& other) {
archive_ = // how do I copy an abstract class?
}
~Archive() { delete archive_; }
void passThrough(ArchiveBase::Data& data) { archive_->passThrough(data); }
Archive& operator = (Archive& other) {
if (this == &other) return *this;
ArchiveBase* newArchive = // can't instantiate....
delete archive_;
archive_ = newArchive;
return *this;
}
private:
ArchiveBase* archive_;
}
ArchiveBase.hpp
class ArchiveBase {
public:
// Is there any way to put this struct in Archive instead,
// so that outside classes instantiating one could use
// Archive::Data instead of ArchiveBase::Data?
struct Data {
int field;
};
virtual void passThrough(Data& data) = 0;
/* more methods */
}
ArchiveDerived.hpp“派生”为“Zip”或“Rar”
#include "ArchiveBase.hpp"
class ArchiveDerived : public ArchiveBase {
public:
ArchiveDerived(string path);
void passThrough(ArchiveBase::Data& data);
private:
/* fields needed by minizip/unrarlib */
// example zip:
unzFile zipFile_;
// example rar:
RARHANDLE rarFile_;
}
ArchiveDerived.cpp
#include "ArchiveDerived.hpp"
ArchiveDerived::ArchiveDerived(string path) { //implement }
ArchiveDerived::passThrough(ArchiveBase::Data& data) { //implement }
有人建议我使用这种设计,这样我就可以做到:
Archive archiveFile(pathToZipOrRar);
archiveFile.passThrough(extractParams); // yay polymorphism!
如何为 Archive 编写 cctor?
存档的 op= 怎么样?
如何将
ArchiveBase::Data
“重命名”为Archive::Data
? (minizip 和 unrarlib 都使用此类结构进行输入和输出。数据对于 Zip 和 Rar 是通用的,稍后用于创建相应库的结构。)其他所有内容都通过Archive
访问,我会也喜欢以这种方式在外部类中声明Data
。
我知道我可以扔掉当前的类Archive
,将ArchiveBase
命名为Archive
,并使用全局工厂函数。但是,我想避免使用全局函数。
最佳答案
首先,您无法“复制”抽象类,因为您无法实例化抽象类。相反,您应该做的是设置该类的 std::tr1::shared_ptr 并传入一个指针。
Archive(ArchiveBase *_archiveBase)
使用 Archive 类之外的工厂函数进行实例化。
Archive createArchive(string _path, int _type){
switch(type) {
case RAR:
return Archive( new ArchiveRar(path) );
case ZIP:
return Archive( new ArchiveZip(path) );
case UNKNOWN_ARCHIVE:
throw exception("Unknown archive format");
break;
default:
throw exception("Improper archive type");
}
对于 = 运算符,只需持有这样的智能指针并使用“=”即可在类之间执行知识的安全传输。它执行引用计数并删除指针,因此您不必这样做,并且只有在安全的情况下才可以这样做。
Archive& operator = (Archive& other) {
m_ArchiveBasePtr = other.m_ArchiveBasePtr;
return *this;
}
让智能指针为您操心删除、复制以及所有这些事情。
关于c++ - 如何为带有 ptr 的工厂类编写 cctor 和 op= 来抽象成员字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2535362/