Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:在基模板类中调用派生的专用虚拟函数_C++_Templates_Polymorphism - Fatal编程技术网

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

C++ C++;:在基模板类中调用派生的专用虚拟函数,c++,templates,polymorphism,C++,Templates,Polymorphism,假设我有以下模板类: 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(); } }; 模板 甲级 { 公众: //很

假设我有以下模板类:

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();
    }
};
模板
甲级
{
公众:
//很多功能。。。
void someFunc(T obj)
{
//T必须实现此函数才能在类A中使用。
obj.interfaceFunc();
}
};
这很好,因为我将与模板类一起使用的对象实现interfaceFunc()

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

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();
    }
};
模板
甲级
{
公众:
//很多功能。。。
虚拟无效虚拟帮助敷衍(T*obj)
{
//我们永远不应该站在基层。
断言(假);
}
void someFunc(T obj)
{
//调用虚拟函数。
虚拟服务敷衍(obj);
}
};
//部分专业化1
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T*obj)
{
obj->interfaceFunc();
}
};
//部分专业化2
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T*obj)
{
obj->interfaceFunc();
}
};
但是,在B的实例上调用VirtualHelpConfunction()时,但在父A的someFunc()函数中,它会遇到断言错误:

B<SomeObject> instance;
instance.someFunc(SomeObject());  // Assertion failure.
B实例;
instance.someFunc(SomeObject());//断言失败。
为了解决这个问题,我尝试过使用函数指针,但我对它们还是相当陌生,非静态指针语法让我有点困惑。我假设可以定义一个指向virtualHelpConfunction()的成员指针,该指针设置为指向a的构造函数中的基类版本,但随后在B的构造函数中被覆盖以指向B的函数。如果是这样的话,有没有人能够演示正确的语法

谢谢

编辑:如果需要上下文,模板类是一个八叉树节点,它存储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();
    }

    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();
    }
};
模板
甲级
{
公众:
//很多功能。。。
虚拟无效虚拟帮助敷衍(T*obj)
{
//我们永远不应该站在基层。
断言(假);
}
void someFunc(T obj)
{
//调用虚拟函数。
虚拟服务敷衍(obj);
}
};
//部分专业化1
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T&obj)
{
obj.interfaceFunc();
}
};
//部分专业化2
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T*obj)
{
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);
    }
};

// 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);
}
模板
甲级
{
公众:
//很多功能。。。
虚拟无效虚拟帮助敷衍(T*obj)
{
//我们永远不应该站在基层。
断言(假);
}
void someFunc(T obj)
{
//调用虚拟函数。
虚拟服务敷衍(obj);
}
};
//非专用模板
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T*obj)
{
obj->interfaceFunc();
}
};
//部分专业化
模板
B类:公共A
{
公众:
// ...
虚拟无效虚拟帮助敷衍(T**obj)
{
(*obj)->interfaceFunc();
}
};
int main(){
B实例1;
instance1.someFunc(SomeObject());
B实例2;
某物x;
instance2.someFunc(&x);
}

这似乎太复杂了。如果你只需要一点点专门化,为什么要专门化整个类呢?您所需要的只是一个小实用程序,它说“如果它是指针,请取消对它的引用,否则请别管它”。它可能是这样的:

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();
}
模板
T&deref_if_指针(T&T){返回T;}
模板
T&deref_if_指针(T*T){return*T;}
// ...
void someFunc(T obj){
deref_if_指针(obj).interfaceFunc();
}

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

在第二个部分专门化中,
virtualHelpConfunction
函数获取指向
T
的指针,即
T**
。使用普通的成员取消引用操作符
->
将失败,我甚至不认为它会编译!在我的实际测试中,我预计需要这样做,但直到我将它们都切换到->时,它才真正编译;实例->someFunc(SomeObject());但是,如果我传递一个指向模板类的指针,那么编译将失败,因为取消引用语法不正确。。。你能展示你做了什么,结果是什么吗?真的不清楚您遇到了什么问题。如果我传入一个指针,类中调用obj.interfaceFunc()的部分将失败,因为编译器将期望obj->interfaceFunc()。要澄清的是,如果t是一个对象指针,它不会变成t**obj和t*obj,还是我得到了错误的结果?第一个问题,为什么它不是一个对象指针?第二个问题,不需要是对象指针吗?还有一个问题,是吗