覆盖模板化类中的虚函数时出错

时间:2017-12-05 04:10:42

标签: c++ templates inheritance c++17 pure-virtual

我遇到覆盖纯虚函数的问题[getContents()]: 我试图继承一个类,fpmessage与派生类fpmessageImpl

然而,当我尝试实例化它时,编译器报告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(在main中):

#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;
}

1 个答案:

答案 0 :(得分:1)

 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-parlance

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