【问题标题】:Error in overriding virtual function in templated class覆盖模板类中的虚函数时出错
【发布时间】:2018-05-18 15:53:44
【问题描述】:

我在覆盖纯虚函数 [getContents()] 时遇到问题: 我正在尝试使用派生类 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(在 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;
}

【问题讨论】:

  • fpmessage&lt;T&gt;::~fpmessage()有什么定义吗?
  • 请逐字包含错误消息,而不是解释
  • 你能把它转换成Minimal, Complete, and Verifiable example吗?
  • auto mess = std::make_shared&lt;fpmessage&lt;fpMessagingDataStates::States&gt;&gt;(m); std::shared_ptr<fpmessage<fpMessagingDataStates::States>> mess = std::make_shared<fpmessageImpl<fpMessagingDataStates::States>>(m); 的操作
  • 请停止膨胀这个问题。您不需要保留它的完整历史记录。只需发布最小的示例和您的问题,仅此而已。

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


【解决方案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 的说法

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

【讨论】:

  • 我有一个函数:fn(const Base& b){auto a = make_shared(b);}。是否有某种方法可以直接复制(通过内存或其他方式)传递给此函数的 Derived 以便能够创建一个?例如。克隆到 shared_ptr 中?
  • @DavidTurner make_shared&lt;Base&gt;(anything) 创建一个新的Base 所以它不会帮助你。如果您需要新的Derived,您需要在某处致电make_shared&lt;Derived&gt;(..)。也许在一个虚拟的clone 方法中。
  • 谢谢。查看在 base 中具有虚拟 clone_shared 函数的实现,并在继承方法中使用 std::dynamic_pointer_cast。
猜你喜欢
  • 2021-11-08
  • 2014-08-16
  • 2014-03-08
  • 1970-01-01
  • 2017-06-28
  • 2014-02-06
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多