2014-11-01 2 views
2

Я хочу создать класс-оболочку на C++, который реализует передачу файлов с использованием FTP, SFTP.Создайте хороший класс оболочки C++, который обертывает множество функций

У меня есть базовый класс FileTransfer (с помощью curl), который наследуется производным классом FTP. Мне нужно поддерживать SFTP, поэтому я реализовал другой производный класс SFTP, который также наследует от FileTransfer.

Я делаю код класса оболочки по следующим строкам. Однако это не похоже на хороший дизайн. Я относительно новичок в ООП, хотя в прошлом я работал над 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 check каждый раз, чтобы поддерживать SFTP. Я не хочу раскрывать детали (FTP/SFTP) вызывающему.

+1

Почему вы используете wraper? – Vincent

+2

Вам нужна обертка? Похоже, что для большинства из них вы можете просто «FileTransfer *», который является либо «FTP», либо «SFTP *». Определенно не * оба указателя, и определенно не 'void *'. – Barry

+0

Я использую оболочку, потому что во многих местах проекта используется существующий объект FTP, и если я использую отдельный класс для SFTP (без оболочки), мне придется каждый раз добавлять проверку 'if' также поддерживают SFTP. Я хочу, чтобы вызывающие абоненты не знали, является ли это FTP или SFTP. –

ответ

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'. –

+0

Предположим, вместо того, чтобы возвращать 'void'' use_passive' возвращенный int ('int() {}'), это дает ошибку 'FileTransfer :: use_passive должен возвращать значение'. Я не могу сделать это чистой виртуальной функцией, так как это сделает класс Abstract, и мне придется реализовать 'use_passive' в классе SFTP. Что можно сделать, чтобы предотвратить это? –

2

Все, что вам нужно, это polymorphism с помощью указателя на FileTransfer, что делает do_something() и виртуальные функции ~FileTransfer() деструктора (т.е. вы invoque функции на указатель базового объекта, а объект будет вызывать правильную функцию в зависимости от его реального класса).

Остается вопрос только о строительстве вашего объекта на основе протокола. Правильный термин не будет «оберткой», а «factory» (шаблон проектирования). Это может быть реализовано с помощью статической функции-члена FileTransfer.

Смежные вопросы