繁体   English   中英

C ++:在基本模板类中调用派生的专用虚拟函数

[英]C++: Calling derived specialised virtual functions within a base template class

假设我有以下模板类:

template<typename T>
class A
{
public:
    // Lots of functions...

    void someFunc(T obj)
    {
        // T must implement this function in order to be usable within class A.
        obj.interfaceFunc();
    }
};

这很好用,因为我将与模板类一起使用的对象实现interfaceFunc()。

但是,如果将指针传递给模板类,则编译会失败,因为取消引用语法不正确。 因为模板类包含许多其他函数,但如果可以帮助的话,我不想将其复制/粘贴到另一个部分专业化中,所以我将类定义更改如下:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

但是,当在B的实例上调用virtualHelperFunction()时,但是在父A的someFunc()函数内部时,它将触发断言错误。

B<SomeObject> instance;
instance.someFunc(SomeObject());  // Assertion failure.

我已经尝试过使用函数指针来解决这个问题,但是我对它们还是很陌生,并且非静态指针语法使我有些困惑。 我假设可以定义一个指向virtualHelperFunction()的成员指针,该指针被设置为指向A的构造函数中的基类版本,但随后在B的构造函数中将其覆盖以指向B的函数。 如果是这样,谁能证明正确的语法来做到这一点?

谢谢。

编辑:如果需要上下文,则模板类是一个八叉树节点,该八叉树节点存储类型T的哈希表。所需的接口函数是对象可以返回边界框,以便根据对象是否受限制进行递归插入与树节点的边界相交。

https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc/worldculltreenode.h https://github.com/x6herbius/crowbar/blob/qt3d-experimental/Modules/Octree/inc /worldculltreenode.tcc

这似乎太复杂了。 如果只需要一点点专业知识,为什么还要对整个班级进行专业训练呢? 您只需要一个小的实用程序,上面写着“如果是指针,请取消引用,否则请不要使用它”。 它可能看起来像这样:

template <typename T>
T& deref_if_pointer(T& t) { return t; }
template <typename T>
T& deref_if_pointer(T* t) { return *t; }

// ...
void someFunc(T obj) {
  deref_if_pointer(obj).interfaceFunc();
}

您也可以轻松地将deref_if_pointer扩展到各种智能指针; 只需添加另一个重载。

我不太确定要完成什么,所以我不得不猜测。 以下内容不能满足您的问题?

class A
{
public:
    // Lots of functions...

    void someFunc(T* obj)
    {
        // T must implement this function in order to be usable within class A.
        obj->interfaceFunc();
    }

    void someFunc(T obj)
    {
        // T must implement this function in order to be usable within class A.
        obj.interfaceFunc();
    }
};

如果要这样做,则需要在第一个部分专业化中使用引用而不是指针:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Partial specialisation 1
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T& obj)
    {
        obj.interfaceFunc();
    }
};

// Partial specialisation 2
template<typename T*>
class B : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

您的代码无法编译。 template<typename T*>是非法的,并且您没有声称的任何部分专业化知识。

这有效:

template<typename T>
class A
{
public:
    // Lots of functions...

    virtual void virtualHelperFunction(T* obj)
    {
        // We should never be here in the base class.
        assert(false);
    }

    void someFunc(T obj)
    {
        // Call the virtual function.
        virtualHelperFunction(&obj);
    }
};

// Unspecialized template
template<typename T>
class B : public A<T>
{
public:
    // ...

    virtual void virtualHelperFunction(T* obj)
    {
        obj->interfaceFunc();
    }
};

// Partial specialisation
template<typename T>
class B<T*> : public A<T*>
{
public:
    // ...

    virtual void virtualHelperFunction(T** obj)
    {
        (*obj)->interfaceFunc();
    }
};

int main() {
    B<SomeObject> instance1;
    instance1.someFunc(SomeObject());

    B<SomeObject*> instance2;
    SomeObject x;
    instance2.someFunc(&x);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM