【问题标题】:C++ multiple template pure virtual inheritanceC++多模板纯虚继承
【发布时间】:2016-11-14 17:19:42
【问题描述】:

通过使用带有父级解析的模板,我已经设法在使用来自多个父级的重载函数时消除了歧义错误,但是在查找 AddObjectImpl 时会出现链接器错误,这很奇怪,因为该函数是虚拟的。

template<typename T>
class ObjectHandler
{
public:
    virtual void AddObjectImpl(T& obj) = 0;
    virtual void ClearObjectImpl(T& obj) = 0;
};

class INTERFACE_API IModel
    : public ObjectHandler<type1>,
    public ObjectHandler<type2>
{
public:
    template<typename T>
    void AddObject(T& obj)
    {
        this->ObjectHandler<T>::AddObjectImpl(obj);
    }
    template<typename T>
    void ClearObject(T& obj)
    {
        this->ObjectHandler<T>::ClearObjectImpl(obj);
    }
};
// In different project
class CModel : public IModel
{
    virtual void AddObjectImpl(type1& o) override;
    virtual void AddObjectImpl(type2& o) override;
    virtual void ClearObjectImpl(type1& o) override;
    virtual void ClearObjectImpl(type2& o) override;
}
// And then the implementation ...

EDIT1:错误发生在调用 AddObject 时:

 error LNK2019: unresolved external symbol 
 "__declspec(dllimport) public: virtual void __cdecl
 ObjectHandler<class type1>::AddObjectImpl(class type1 &)"
 (/*removed*/) referenced in function "public: void __cdecl
 IModel::AddObject<class type1>(class type1 &)"

【问题讨论】:

  • 你得到的错误是什么?
  • this-&gt;ObjectHandler&lt;T&gt;::AddObjectImpl(obj); 不是虚拟通话。你应该试试((ObjectHandler&lt;T&gt;*) this)-&gt;AddObjectImpl(obj)
  • @Franck 这似乎有效,但我不明白为什么它不是虚拟通话,以及为什么你的答案有效。如果您可以添加您的答案以便我选择它,谢谢:)

标签: c++ inheritance linker


【解决方案1】:

在您的代码中,this-&gt;ObjectHandler&lt;T&gt;::AddObjectImpl(obj); 不是虚拟/动态调用,而是静态调用,因为您对调用进行了限定。

您应该将其替换为 ((ObjectHandler&lt;T&gt;*) this)-&gt;AddObjectImpl(obj) 以调用正确的虚拟方法。

在类似的代码中

class Base {
  public:
    virtual void f();
};
class Derived : public Base {
  public:
    virtual void f();
};

Base* base = new Derived;

电话

base->Base::f();

静态调用基本方法Base::f,而((Base*) base)-&gt;f()通过在虚拟方法表中搜索动态调用Derived::f。您的代码也是如此。

注意与

class Base {
  public:
    virtual void f() = 0;
};
class Derived : public Base {
  public:
    virtual void f() {}
};

Base* base = new Derived;
base->Base::f();

编译器会编译它,即使它可以推断出它是对纯虚方法的静态调用。最后,链接器抱怨错误消息undefined reference to Base::f()

【讨论】:

    猜你喜欢
    • 2014-11-06
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 2012-10-11
    • 2012-01-31
    相关资源
    最近更新 更多