簡體   English   中英

指向函數和派生類的指針

[英]Pointers to functions and derived classes

我在g ++以及模板如何與函數指針交互方面遇到問題。 考慮以下模板聲明。

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(),因為它引起了問題。 這是使用此模板的代碼。

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()傳遞了一個指向返回Derived實例的函數的指針,而TestTemplate聲明testfcnBAD()采取了指向返回Base對象的函數的指針。 由於Derived對象 Base對象,因此該代碼似乎應該可以,但是Derived是Base的子類的事實可能會丟失。

我在這里缺少什么嗎,有什么解決方法嗎?

我不是C ++標准的專家,但是據我所知,協變返回類型僅在覆蓋函數時適用。 您不能將協變返回類型與函數指針一起使用。 我會提出類似的建議:

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));
};

給定您的代碼,如果您可以將Derived *(Derived:: *)()Base *(Base:: *)() ,則會違反類型安全性:

Derived *(Derived:: *derived_method)()= &Derived::returnDerivedBAD;
Base *(Base:: *base_method)()= derived_method;
Base b;
(b.*base_method)(); // would compile, but invalid at runtime! Oops!

因此,您不能安全地“解決它”。 即使您將返回類型更改為匹配,它仍然會違反類型安全性。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM