指向虚函数的指针

时间:2014-01-09 20:52:17

标签: c++ function pointers virtual

所以我现在处于一种两难境地。我想制作一个函数指针,但我想把它变成一个虚函数。不一定是虚函数本身,而是衍生的函数。我试过制作指针,但函数需要是静态的。当我尝试创建静态虚函数时,编译器会对我大喊大叫。我也不想让函数指针类具体,所以可以想象其他类可以使用指针。这就是我在伪代码中的意思:

class C
{
public:
    virtual void something();
};

class B : public C
{
public:
    void something();
};

class D
{
public:
    void something();
};


int main()
{
    void(*pointer)();
    B b;
    D d;
    pointer = b.something.
    pointer();
    pointer = d.something;
    pointer()
}

某些东西不是静态方法,但我希望指针能够指向它。指针也可以指向其他非静态的类方法。我有什么可以做的吗?

修改 我终于能够弄清楚如何做到这一点。我不得不使用std :: function。这也适用于常规成员函数,不一定是虚函数。这是它的样子:

class A
{
 public:
virtual void something(int i);
};
class B
{
virtual void somethingElse(int i);
}
//This isn't needed, it just saves typing if you have multiple pointers
typedef std::function<void(int)> functionType
functionType* pointer;

int main()
{
 B b;
 A a;
 pointer = std::bind(&A::something,&a,std::placeholders::_1);
 pointer(1)
 pointer = std::bind(&B::somethingElse,&b,std::placeholders::_1);
 pointer(4)
}
在pd :: bind的互联网上有很多,所以如果你很好奇,你可以阅读它。 我发现这特别有用,因为它与我的解决方案非常相似。 std::function to member function 感谢所有帮助过的人。

5 个答案:

答案 0 :(得分:3)

您将无法将指针指向成员函数分配给普通函数指针:当成员函数将隐式this指针作为参数时,函数指针不会采用任何其他参数。您可能希望使用std::function<...>

std::function<void()> pointer;
B b;
pointer = std::bind(&C::something, &b);
pointer();
D d;
pointer = std::bind(&c::something, &d);
pointer();

如果你传递一个指向对象的指针,并且在周围有一个合适的成员函数指针,那么你可以避免使用std::function<...>有一个共同的基类(而上面的代码与缺少的继承一起工作) ,以下代码要求CD}的基础:

void (C::*member)() = &C::something;
C* c = &b;
(c->*member)(); // calls b.something() using B::something()
c = &d;
(c->*member)(); // calls d.something() using D::something()

C ++没有使用&object.member来表示容易绑定的成员函数的地址。 ......而且,即使它确实如此,它的类型也不会是void(*)()

答案 1 :(得分:2)

void(B::*bPointer)();
void(D::*dPointer)();
B b;
D d;
bPointer = &B::something;
(b.*bpointer)();
dPointer = &D::something;
(d.*dPointer)();

您还可以使用std::mem_fnstd::bind

答案 2 :(得分:1)

这里有很多错误,很难知道从哪里开始。

此:

void(*pointer)();

声明指向成员函数的指针。它声明了一个指向自由函数的指针(例如,非成员函数)。这两种类型的指针是完全不相关的,你不能在两者之间进行转换。您不能将成员函数的地址分配给指向自由函数的指针,反之亦然。

您需要使用特殊语法声明指向成员的指针。旧的(C ++ 03)语法是:

void (C::*memFn)()

但是,由于指针的类型包含有关该函数所属的类的信息,现在您无法将地址D::something()分配给memFn - CD完全无关。

您提到要创建“静态虚拟方法”。没有这样的事情。事实上,“静态”和“虚拟”这两个概念几乎完全相互正交。这个想法毫无意义。这就像是说你要种一个苹果锤。

为什么要尝试将D对象用作B对象? DB完全无关。在我看来,你真正应该做的是拥有一个抽象基类A,以及该ABC的{2}和B的两个具体实现。然后,指向C的指针可能指向AB,您可以调用同名的C方法并获得不同的行为。

最后,在过去的几天里,您发布的问题表明您正在努力学习该语言,方法是敲击一些代码并尝试修复编译器错误的结果。 (我可能会想到其他人,如果是的话,我很抱歉)这不会起作用。你接受了我的建议并获得了good C++ text吗?

答案 3 :(得分:0)

S.th。像

 pointer = &D::dosomething;

可能是??

注意:
您需要有一个D的实际实例来调用非静态类成员。

答案 4 :(得分:0)

#include <iostream>

class A
{
    private:
        int i;

    protected:
        void (A::*ptr)();

    public:
        A() : i(0), ptr(&A::methodOne) {}
        virtual ~A(){}

        void move_ptr()
        {
            switch(++i)
            {
                case 0: {ptr = &A::methodOne;} break;
                case 1: {ptr = &A::methodTwo;} break;
                case 2: {ptr = &A::methodThree;} break;
                case 3: {ptr = &A::nonVirtual;} break;
                default: {ptr = &A::methodOne; i = 0;} break;
            }
        }

        void call() {(this->*A::ptr)();}

        virtual void methodOne() {std::cout<<"A::methodOne\n";}
        virtual void methodTwo() {std::cout<<"A::methodTwo\n";}
        virtual void methodThree() {std::cout<<"A::methodThree\n";}
        void nonVirtual() {std::cout<<"A::nonVirtual\n";}
};

class B : public A
{
    public:
        B() : A() {}
        virtual ~B(){}

        virtual void methodOne() {std::cout<<"B::methodOne\n";}
        virtual void methodTwo() {std::cout<<"B::methodTwo\n";}
        virtual void methodThree() {std::cout<<"B::methodThree\n";}
        void nonVirtual() {std::cout<<"B::nonVirtual\n";}
};

int main()
{
    A a;
    a.call();
    a.move_ptr();
    a.call();
    a.move_ptr();
    a.call();
    a.move_ptr();
    a.call();


    B b;
    b.call();
    b.move_ptr();
    b.call();
    b.move_ptr();
    b.call();
    b.move_ptr();
    b.call();
}

打印:

A::methodOne
A::methodTwo
A::methodThree
A::nonVirtual

B::methodOne
B::methodTwo
B::methodThree
A::nonVirtual

我会留给你弄清楚为什么最后一行是A::nonVirtual而不是B::nonVirtual。一旦你搞清楚了,你就已经知道如何修复它了。