2

如果我聲明:C++模板和繼承與方法指針

class Avoidance : public Schema<std_msgs::String,prog1::Command>{ 

我嘗試

void*(Schema<std_msgs::String,prog1::Command>::*pt)(); 
    pt=&Avoidance::frontBusy; 

編譯舉報我

error: cannot convert ‘void* (Avoidance::*)()’ 
to 
‘void* (Schema<std_msgs::String_<std::allocator<void> >, prog1::Command_<std::allocator<void> > >::*)()’ in assignment 

爲什麼呢?避免繼承

Schema<std_msgs::String,prog1::Command> 

然後避免是架構< .....>

+0

你的答案是這裏給出:爲什麼我不能投一個指向派生類的成員函數相同,但Base類](http://stackoverflow.com/questions/10162823/why-cant -i-cast-a-pointer-derived-class-member-function-to-the-same-but-of-c) –

回答

2

擺脫模板來簡化,假設你有

class B { 
public: 
    void f(); 
}; 

class D : public B { 
public: 
    void g(); 
}; 

它可能看起來有點倒退,但你可以投void (B::*)()void (D::*)(),但你不能投void (D::*)()void (B::*)()。當你考慮如何使用它們時,這是有道理的。

void test() { 
    void (D::*p)() = &B::f; // OK! 
    void (B::*q)() = &D::g; // ERROR! 

    B b; 
    D d; 

    (d.*p)(); // Calls B::f on `d`. Okay, `B::f` is an inherited member. 
    (b.*q)(); // Calls D::g on `b`?? But that's not a member of `b` at all! 
} 
+0

//在'b'上調用D :: g?但是那根本不是'b'的成員! 好的,但在一般鑄造中也存在同樣的問題;如果我將基類轉換爲基類,我知道我不能訪問未在基類中聲明的類存在成員,這是一條常用規則;爲什麼在函數指針中不要簡單地做同樣的事情? – volperossa

+0

我描述的規則適用於隱式轉換。明確的演員陣容更慷慨,更危險。就像你可以隱式地將'D *'轉換爲'B *'一樣,但你只能通過明確的轉換將'B *'轉換爲'D *'。 – aschepler

3

這不是如何成員函數指針的工作。如果frontBusy是基本函數,則需要適當地鍵入指針。儘管如此,調度仍將按預期工作!

這裏有一個基本的例子:

struct A { virtual void f() = 0; }; 
struct B : A { virtual void f() { } }; 

void dispatch(void (A::*pf)(), A & a) 
{   // ^^^^^ 
    (a.*pf)(); 
} 

int main() 
{ 
    B x; 
    dispatch(&A::f, x); // calls x.B::f() 
} //  ^^^^^ 

所以,你的情況,你想:

void (Schema<std_msgs::String,prog1::Command>::*p)() 
         = &Schema<std_msgs::String,prog1::Command>::frontBusy;