C++ 中静态和动态多态性的代码?

问题描述 投票:0回答:1

我尝试在需要擦除的基础上实现适合动态和静态多态性的类,即仅在必须时才使用动态多态性(例如异构列表)。我写了以下代码

class Connection {
public:
Connection& operator=(Connection& c) = delete;
Connection(Connection& c) = delete;
Connection& operator=(Connection&& c) = delete;
Connection(Connection&& c) = delete;
virtual ~Connection() = 0;
virtual string Recv() = 0;
}

template<typename T>
class IConnection : Connection{
public:
inline T* dispatch(){
   return static_cast<T*>(this);
}
virtual string Recv() override{
    return dispatch()->Recv();
}
...
}

但是,如果我要实现

class Socket :IConnection<Socket>
,那么
Recv()
中的
class Socket
仍然是动态调度。

有没有解决方法,以便我可以使用

IConnection<Socket> s{Socket{...}}; // statically
Connection c{Socket{...}};          //dynamically
c++ oop inheritance design-patterns crtp
1个回答
0
投票

当您继承

Connection
时,您的问题就开始了。 您将
Connection
定义为抽象类,这意味着编译器将生成一个 vtable 和所有这些有趣的玩具。
期望
Connection*
的事物期望 vtable 等。
但同时,您希望
Connection
界面有时是静态的。这意味着调用者将不得不改变他们调用内容的方式。但这是两种截然不同的类型,具有两种截然不同的调用约定。
您不能在同一界面下同时拥有两者。\

您可以做的是一个模板化的

Connection
类,它接收一个类型并假设该类型具有您期望的函数,并在具有相同名称的函数中调用它们。您将无法将其传递给需要
Connection*generically
的东西,但它可能仍然适合您的需求。

template <typename T>
class Connection {
public:
    Connection(T&& impl) : _impl(impl) {}
    std::string recv() { return _impl.recv(); }
    ... rest of your implementation...
private:
    T impl;
};

这样,如果

foo
是实现某个需要
recv()
的接口的对象,
Connection<foo>
将使用 vtable,并且您将拥有动态调度。如果您构造一个
Connection<bar>
,其中 bar 是一个普通类,恰好有一个
recv()
方法,它仍然可以工作,并且您将获得静态调度。

© www.soinside.com 2019 - 2024. All rights reserved.