在模板化 class 中重写虚函数时出错

Error in overriding virtual function in templated class

我在覆盖纯虚函数 [getContents()] 时遇到问题: 我正在尝试继承一个 class,带有派生的 class fpmessageImpl

的 fpmessage

但是,当我尝试实例化 fpmessageImpl 时,编译器报告它是虚拟的,因为 getContents() 是一个未实现的纯虚函数(尽管覆盖没有问题)。这里发生了什么,有没有办法解决它? clang++ 错误报告的最后一部分:(fpmessagingSystemImpl 中的违规代码已移至 MWE 中的 main)

src/fpmessagingsystemimpl.h:56:7: note: in instantiation of member function 'fp::utils::fpmessagingSystemImpl<fp::utils::fpMessagingDataStates::States>::send_message' requested here
      fpmessagingSystemImpl(std::map<MessageType,std::type_index> m) noexcept :
      ^
src/fpengineimpl.h:19:21: note: in instantiation of member function 'fp::utils::fpmessagingSystemImpl<fp::utils::fpMessagingDataStates::States>::fpmessagingSystemImpl' requested here
      msg_sys = new fp::utils::fpmessagingSystemImpl<fp::utils::fpMessagingDataStates::States>(ds.get_map());
                    ^
src/fpmessagingsystem.h:32:48: note: unimplemented pure virtual method 'getContents' in 'fpmessage'
      virtual std::tuple<MessageType,std::any> getContents() const noexcept = 0;

可重现的例子: 问题似乎在于 std::make_shared 如何构建新的 fpmessage(主要):

#include <memory>
#include <any>
#include <map>
#include <typeindex>

class fpMessagingDataStates {
public:
  enum class States{
    INIT
  };
  const std::map<fpMessagingDataStates::States,std::type_index> get_map() {
    return m;
  }
  fpMessagingDataStates(){
    m = std::map<fpMessagingDataStates::States,std::type_index>();
    m.emplace(std::make_pair(fpMessagingDataStates::States::INIT,std::type_index(typeid(std::wstring))));
  }
private:
  std::map<fpMessagingDataStates::States,std::type_index> m;
};

template<typename MessageType>
class fpmessage{
public:
  fpmessage(MessageType mt, std::any a) noexcept {};
  virtual bool validate_message (const std::map<MessageType,std::type_index>& map) const noexcept {return false;}
  virtual std::tuple<MessageType,std::any> getContents() const noexcept = 0;
  /*virtual ~fpmessage();*/
protected:
  fpmessage() {};
};

template<typename MessageType>
class fpmessageImpl : public fpmessage<MessageType>{
public:
  fpmessageImpl() = delete;
  fpmessageImpl(MessageType mt, std::any a) :
    t(mt),
    contents(a) {}
  // check stored message type against a map
  virtual bool validate_message(const std::map<MessageType,std::type_index>& map) const noexcept override{
    // check the expected message type against the actual type
    auto expected_type = map.find(t);
    return (expected_type->second == std::type_index(contents.type()));
  }
  virtual std::tuple<MessageType,std::any> getContents() const noexcept override {
    return std::make_tuple(t,contents);
  }
private:
  const MessageType t;
  const std::any contents;
};

int main(int argc, char** argv)
{
  std::wstring s = L"Engine Started";
  auto state = fpMessagingDataStates::States::INIT;
  auto m = fpmessageImpl<fpMessagingDataStates::States>(state, s);
  auto mess = std::make_shared<fpmessage<fpMessagingDataStates::States>>(m);
  return 0;
}
 auto m = fpmessageImpl<fpMessagingDataStates::States>(state, s);
 auto mess = std::make_shared<fpmessage<fpMessagingDataStates::States>>(m);

出于说明目的重命名和简化:

auto d = Derived();
auto bp = std::make_shared<Base>(d);

这是一个美化的 c++11 风格的包装器,围绕着旧的东西

 Derived d;
 Base* pb = new Base(d);

第二行不会创建Derived类型的对象。它将创建一个 Base 类型的对象,并从 Derived 参数复制构造它,并在过程中对其进行切片。当然,如果 Base 是抽象的,它将无法编译。

为了复制 d 需要

Base* pb = new Derived(d);

或者用 C++11 的说法

 std::shared_ptr<Base> = std::make_shared<Derived>(d);