首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >函数和派生类的指针

函数和派生类的指针
EN

Stack Overflow用户
提问于 2011-10-14 18:40:59
回答 2查看 125关注 0票数 1

g++和模板如何与指向函数的指针交互存在问题。考虑下面的模板声明。

代码语言:javascript
复制
template <class T,class B> class TestTemplate {

  private:
    T* context;

  public:
    TestTemplate(T* usingClass);

    B* testfcnOK(B* arg);
    B* testfcnBAD(B* (T::*fcn)(void));
};

template <class T,class B> TestTemplate<T,B>::TestTemplate(T* usingClass) {
  context = usingClass;
}

template <class T,class B> B* TestTemplate<T,B>::testfcnOK(B* arg) {
    return arg;
}

template <class T,class B> B* TestTemplate<T,B>::testfcnBAD(B* (T::*fcn)(void)) {
    return (context->*fcn)();
}

将T看作一个类,它包含返回B类型对象的各种函数,上面的方法是testfcnBAD(),因为它会导致问题。下面是使用此模板的代码。

代码语言:javascript
复制
class Base { };
class Derived : public Base { };

class Tester {

  public:
   TestTemplate<Tester,Base> *templateClass;

   Base* returnBase() { return new Base(); }
   Base* returnDerivedOK() { return new Derived(); }
   Derived* returnDerivedBAD() { return new Derived(); }

   void runTest()
     {
       templateClass = new TestTemplate<Tester,Base>(this);

       // These work.
       Base* baseResult = templateClass->testfcnOK(new Base());
       baseResult = templateClass->testfcnOK(new Derived());
       baseResult = templateClass->testfcnBAD(&Tester::returnBase);
       Derived* derivedResult = (Derived*) templateClass->testfcnBAD(&Tester::returnDerivedOK);

       // This does not work.
       derivedResult = (Derived*) templateClass->testfcnBAD(&Tester::returnDerivedBAD);
     }
};

当给出runTest()的最后一行时,g++ (4.5.2)会阻塞。问题似乎是,testfcnBAD()被传递给一个指向返回派生实例的函数的指针,而TestTemplate则声明testfcnBAD()接受一个指向返回Base的函数的指针。这段代码看起来应该是可以的,因为派生对象是Base对象,但是派生对象是Base的子类这一事实可能会在这条线的某个地方丢失。

我是不是漏掉了什么东西,还有什么可以解决的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-14 18:54:56

我不是C++标准方面的专家,但据我所知,协变量返回类型只适用于重写函数时。不能使用带有函数指针的协变量返回类型。我会提出如下建议:

代码语言:javascript
复制
template <class T,class B> class TestTemplate {

  private:
    T* context;

  public:
    TestTemplate(T* usingClass);

    B* testfcnOK(B* arg);
    template<typename D> B* testfcnBAD(D* (T::*fcn)(void));
};
票数 1
EN

Stack Overflow用户

发布于 2011-10-14 20:02:41

给定您的代码,如果您可以将Derived *(Derived:: *)()转换为Base *(Base:: *)(),则会违反类型安全性:

代码语言:javascript
复制
Derived *(Derived:: *derived_method)()= &Derived::returnDerivedBAD;
Base *(Base:: *base_method)()= derived_method;
Base b;
(b.*base_method)(); // would compile, but invalid at runtime! Oops!

所以你不能安全地“绕过它”。即使您将返回类型更改为匹配,它仍然会违反类型安全性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7772085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档