【问题标题】:c++ template and inheritance with method pointerc ++模板和带有方法指针的继承
【发布时间】:2013-01-02 07:56:29
【问题描述】:

如果我声明:

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>

那么避免是模式<.....>

【问题讨论】:

标签: c++ templates inheritance function-pointers member-pointers


【解决方案1】:

成员函数指针不是这样工作的。如果frontBusy 是基本函数,则需要适当地键入指针。 dispatch 仍将按预期工作!

这是一个基本的例子:

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;

【讨论】:

    【解决方案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!
    }
    

    【讨论】:

    • // 在b上调用 D::g??但这根本不是b 的成员!好的,但是在一般的铸造中也有同样的问题;如果我将继承类转换为基类,我知道我无法访问未在基类中声明的存在的类成员,这是一个通用规则;为什么函数指针不完全一样?
    • 我描述的规则是针对隐式转换的。显式演员表更慷慨也更危险。就像您可以将D* 隐式转换为B*,但您只能通过显式转换将B* 转换为D*
    猜你喜欢
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 2016-08-15
    • 2021-09-16
    • 2014-05-07
    • 1970-01-01
    相关资源
    最近更新 更多