【问题标题】:Abstract template class with pure virtual method in c++C++中具有纯虚方法的抽象模板类
【发布时间】:2019-01-01 17:54:56
【问题描述】:

public/Interface.h

#pragma once

template <typename T>
class BaseInterface {
public:
    virtual void foo() = 0;
};

private/Base.h

#pragma once
#include "../public/Interface.h"

template <typename T>
class Base : public BaseInterface<T> {
public:
   virtual void foo() override;
};

template <typename T>
inline void Base<T>::foo() {
}

main.cpp

#include <iostream>
#include <memory>
#include "public/Interface.h"

int main() {
    auto base = std::make_shared< BaseInterface<std::string> >();
    base->foo();
    return 0;
}    

收到此错误:

/usr/include/c++/5/ext/new_allocator.h:120:4: error: invalid new-expression of abstract class type ‘BaseInterface<std::__cxx11::basic_string<char> >’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }

AbstractPureVirtual/public/Interface.h:4:7: note:   because the following    virtual functions are pure within ‘BaseInterface<std::__cxx11::basic_string<char> >’:
 class BaseInterface {

AbstractPureVirtual/public/Interface.h:6:17: note:  void BaseInterface<T>::foo() [with T = std::__cxx11::basic_string<char>]
virtual void foo() = 0;

虽然我已经覆盖了派生类中的纯虚方法,但我得到了这个错误,并且看起来它应该是一个模板类。如果我需要做类似的事情,我应该如何实施?

【问题讨论】:

  • 不,这与派生类无关——编译器在编译 main.cpp 时甚至不知道 private/Base.h
  • 不同措辞question,答案基本相同。
  • 您的意思是std::make_shared&lt; Base&lt;std::string&gt;&gt;() 吗?编译器如何知道调用哪个派生类来构造接口类?

标签: c++ templates interface abstract-class


【解决方案1】:

make_shared 创建一个与您指定的类完全相同的对象。它无法知道它的派生类,所以make_shared&lt; BaseInterface&lt;std::string&gt; &gt;()本质上调用了new BaseInterface&lt;std::string&gt;,并且不允许创建抽象类的对象。这与模板无关;如果你用普通类替换它们,错误仍然存​​在。

【讨论】:

    【解决方案2】:
    auto base = std::make_shared< BaseInterface<std::string> >();
    

    您尝试在此处创建BaseInterface&lt;std::string&gt; 类型的具体对象。我怀疑你想要:

    auto base = std::make_shared< Base<std::string> >();
    

    或许

    std::shared_ptr< BaseInterface<std::string> > base = std::make_shared< Base<std::string> >();
    

    【讨论】:

    • 这个确实比较合理。
    • 感谢 L. F. 和 Yakk 的回复。我明白为什么这不起作用。我在这里尝试做的是隐藏具体类的实现细节,只为链接到这个库的应用程序提供一个接口。解决这个问题的最佳方法是什么?
    • @engg 库无法导出模板。有一些导出类型擦除的东西的方法有点像导出模板,但它们在特定方面较弱,而且你的抽象问题没有详细说明你可以接受比模板更弱的东西的方式。这是一种常见的 X/Y 问题;为了得到答案,您可能需要针对具体问题案例提出另一个问题。或者接受“不”。
    猜你喜欢
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2015-08-14
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多