设计一个好的C++包装器类,它包装了多个功能

Design a good C++ wrapper class that wraps around multiple functionalities

本文关键字:包装 功能 一个 C++      更新时间:2023-10-16

我想在C++中设计一个包装类,使用FTP、SFTP实现文件传输。

我有一个基类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)检查并提高代码质量?我应该为psftp和"pftp"使用void指针吗?

编辑:我使用包装器是因为在项目中的很多地方,都在使用现有的FTP对象,如果我为SFTP使用单独的类(没有包装器),我每次都必须添加if检查才能支持SFTP。我不想向调用者公开细节(FTP/SFTP)。

只需使用基类指针,这里的一切都可以更容易地完成。

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;

您所需要的只是使用指向FileTransfer的指针进行多态性,使do_something()~FileTransfer()析构函数成为虚拟函数(即,您在基对象指针上调用函数,对象将根据其真实类调用正确的函数)。

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