【问题标题】:Getting around Qt's templating restrictions绕过 Qt 的模板限制
【发布时间】:2013-11-05 16:08:28
【问题描述】:

我想用 C++ 编写一个简单灵活的 ftp 服务器,它可以用一个类参数化来处理服务器初始化时提供的用户(检查登录名和密码,传递文件等)。

所以我想出了这个巧妙(我想)的想法:

class FtpDelegate
{
public:
    FtpDelegate() {}
    virtual ~FtpDelegate() {}
    virtual bool login(QString username, QString password) = 0;
    // ...
};

class DummyDelegate : public FtpDelegate
{
public:
    virtual bool login(QString username, QString password)
    {
        return true;
    }
};

template<class Delegate>
class FtpServer : public QObject, Derived_from<Delegate, FtpDelegate>
{
    Q_OBJECT
public:
    explicit FtpServer(const QHostAddress &address = QHostAddress::Any,
                       quint16 port = 21,
                       QObject *parent = 0);

public slots:
    void newConnection();

private:
    QTcpServer *server;
    QHostAddress address;
};

template <class Delegate>
void FtpServer<Delegate>::newConnection()
{
    FtpDelegate *delegate = new Delegate();
    new FtpConnection (delegate, server->nextPendingConnection(), address, this);
}

class FtpConnection : public QObject
{
    Q_OBJECT
public:
    explicit FtpConnection(FtpDelegate *delegate,
                           QTcpSocket *socket,
                           const QHostAddress &address,
                           QObject *parent = 0);

public slots:
    void newDataConnection();

private:
    QTcpSocket *socket;
    QTcpServer *dataServer; // needed to transfer data to user
    QTcpSocket *dataSocket;
};


// server initialization
FtpServer<DummyDelegate> ftpServer();

然后(你可能已经看到了)砰!

Error: Template classes not supported by Q_OBJECT

可能还有其他错误或误解,因为我才刚刚开始学习 C++ 模板机制(以及 Qt)。

我的问题是:在不使用丑陋的技巧(如传递函数指针或需要为每个具体的 FtpDelegate 的派生类创建工厂实现)的情况下,使其工作的最佳方法是什么。也许有一些我看不到的聪明的设计模式。最终我可以重写网络机制来提升,如果它是最好的选择。

【问题讨论】:

  • 您为什么希望Delegate 成为FtpServer 类型的一部分?为什么不在FtpServer 中存储指向Delegate 的指针?
  • 这是“正常”继承/多态工作非常好的情况之一,不要仅仅因为大量无用的模板污染你的代码。
  • @TomKnapen 我需要能够为每个新用户连接创建一个新的 Delegate 实例(请参阅 FtpServer::newConnection() 的实现)。
  • @MatteoItalia 我完全是为了简单,但没有找到摆脱这些模板的方法。你能详细说明一下吗?关于继承——我想到的唯一一件事就是合并 FtpDelegate 和 FtpConnection,但无论如何它并不能解决问题。

标签: c++ qt templates design-patterns qtnetwork


【解决方案1】:

无法创建模板 Q_OBJECT 类(请参阅this 和答案)。

您应该使用运行时继承,而不是使用静态继承,并注入一个从 FtpDelegate 类继承的对象。


看起来 FtpServer 实际上是一个创建连接的工厂。从您的问题来看,我不明白为什么它必须是 Q_OBJECT 类。因此,您可能需要重新考虑您的设计,并简化该类。


什么是让它工作的最佳方法,而不使用像传递函数指针或需要为每个具体 FtpDelegate 的派生类创建工厂实现这样的丑陋技巧。

最好的方法可能是创建一个工厂类,它创建FtpDelegate 类型的实例。但是您发布的代码中存在很多问题,如果不知道所有血淋淋的细节,就无法说出更多。

【讨论】:

  • 实际上 FtpServer 确实处理主服务器并将与新连接的对等点关联的套接字(用 FtpServer::newConnection 发出信号)传递给新创建的 FtpConnection 实例。另一方面,FtpConnection 创建一个管理数据传输的新服务器(这是 ftp 规范的要求)。这两个类都继承自 QObject,因此它们可以使用 qt 的信号和槽。我知道我必须重新设计,这就是我寻求帮助的原因:)
猜你喜欢
  • 2019-07-12
  • 2012-04-16
  • 2017-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多