2014-11-01 76 views
2

我想在C++中设计一个使用FTP,SFTP实现文件传输的包装类。设计一个包装多种功能的优秀C++包装类

我有一个基类FileTransfer(使用curl),它是由派生类FTP继承的。我需要支持SFTP,所以我实现了另一个派生类SFTP,它也继承自FileTransfer

我沿着以下几行制作了一个包装类代码。但是,这看起来不是很好的设计。我对OOP比较陌生,尽管过去我曾在C上工作过。

class Wrapper { 
 
    public: 
 
    Wrapper(int m_protocol){ 
 
    protocol = m_protocol; 
 
    if (protocol) 
 
     pftp = new FTP(); 
 
    else 
 
     psftp = new SFTP(); 
 
    } 
 
    
 
    ~Wrapper() { 
 
    if (protocol) 
 
     delete pftp; 
 
    else 
 
     delete psftp; 
 
    } 
 
    //Function supported by both ftp/sftp 
 
    void do_something(){ 
 
    if (protocol) 
 
     pftp->do_something(); 
 
    else 
 
     psftp->do_something(); 
 
    } 
 
    
 
    //FTP specific function 
 
    void use_passive(){ 
 
    assert(protocol); 
 
    pftp->use_passive(); 
 
    } 
 
    
 
    //SFTP specific function 
 
    void ssh_key(){ 
 
    assert(!protocol); 
 
    psftp->ssh_key(); 
 
    } 
 
    
 
    private: 
 
    int protocol; 
 
    FTP *pftp; 
 
    SFTP *psftp; 
 
};

我怎样才能改善这种设计?如何避免每个函数中的if (protocol)检查并提高代码质量?我应该使用void指针作为psftp和'pftp`吗?

编辑:我使用的包装,因为在项目中的很多地方,现有的FTP对象正在使用,如果我使用单独的类为SFTP(没有包装),我将不得不添加一个if检查每次也支持SFTP。我不想将详细信息(FTP/SFTP)公开给调用者。

+1

你为什么使用包装? – Vincent 2014-11-01 15:47:03

+2

你需要包装吗?似乎大多数情况下,您只需要一个'FileTransfer *',它可以是'FTP *'或'SFTP *'。绝对不是*两个*指针,绝对不是'void *'。 – Barry 2014-11-01 15:47:55

+0

我正在使用一个包装,因为在项目中的很多地方,现有的FTP对象正在使用,如果我使用SFTP(没有包装)单独的类,我将不得不添加一个'if'检查每次也支持SFTP。我想让呼叫者不知道它是FTP还是SFTP。 – 2014-11-01 15:51:49

回答

2

只需使用基类指针就可以轻松完成此处的所有操作。

FileTransfer* ft; 
std::unique_ptr<FileTransfer> ft; // C++11 

制作一个:

// should this really be an int? 
FileTransfer* factory(int protocol) { 
    if (protocol) 
     return new FTP; 
    else 
     return new SFTP; 
} 

// in C++11 this should be 
std::unique_ptr<FileTransfer> factory(int protocol); 

做一些:

ft->do_something(); 

做一些具体的事情,以一种或另一种:

// this will die if ft is an SFTP 
dynamic_cast<FTP*>(ft)->use_passive(); 

// but you could check it 
if (FTP* ftp = dynamic_cast<FTP*>(ft)) { 
    ftp->use_passive(); 
} 

// or perhaps even better, make a default virtual that does nothing 
virtual void FileTransfer::use_passive() { } 

void FTP::use_passive() override { // whatever } 

ft->use_passive(); 

删除:

// make sure FileTransfer::~FileTransfer() is virtual!! 
delete ft; 
+0

谢谢。在'FileTransfer'中创建虚拟成员函数更有意义。使用dynamic_cast,调用者将不得不重复创建指向'FTP' /'SFTP'的指针。 – 2014-11-01 21:06:30

+0

让我们假设,不是返回'void',而是use_passive'返回一个int('int(){}'),这会给出错误FileTransfer :: use_passive必须返回一个值。我不能使这个纯虚函数,因为这将使类Abstract,我将不得不在SFTP类中实现'use_passive'。可以做些什么来防止这种情况发生? – 2014-11-02 10:18:13

2

所有你需要的是polymorphism使用指针FileTransfer,使得do_something()~FileTransfer()析构虚函数(即你invoque的基础对象指针的功能,以及对象将调用正确的函数依赖于它真正的类)。

剩下的问题只是关于基于协议的对象构造。正确的术语不是“包装”,而是“factory”(设计模式)。这可以通过FileTransfer的静态成员函数来实现。