Передача (возможно) виртуального метода в качестве указателя на функцию в C ++ - PullRequest
1 голос
/ 27 июня 2011

Мне нужно преобразовать этот код в вызов указателя функции для Visual Studio 2008. Функция GetValue() может быть виртуальной, но не всегда, и GetObject() в разных контекстах будет возвращать разные типы.

...
res = GetObject()->GetValue(x, y);
...

Вызывающая функция передаст GetObject()->GetValue (указатель на func + экземпляр объекта, для которого должна быть вызвана эта функция), а параметры будут предоставлены функцией вызываемого абонента:

void Foo(  (int T::func*)(int, int)  )
{
    ...
    res = func(x, y);
    ...
}

void Bar()
{
    Foo( & GetObject()->GetValue );
}

Спасибо!

Ответы [ 4 ]

5 голосов
/ 27 июня 2011

Вы действительно хотите std::tr1::function<int(int int)> для этой работы. Проверьте документацию на MSDN, и вы станете счастливым человеком.

0 голосов
/ 27 июня 2011

Ваши функции являются глобальными, поэтому ваш объект может быть глобальным, с функцией-оболочкой:

public class MyMsgObject
{
    void ShowMsg(char[] Msg);

    // other methods
};

// ...

// this function belongs to a class, is a method
void MyMsgObject::ShowMsg(char[] Msg)
{
    cout << "Method: " << Msg <<"\n";
}

// this method doesn't belong to any class,
// its global
void GlobalShowMsg(char[] Msg)
{
    cout << "Global: " << Msg <<"\n";
}

// global var obj, before method wrapper:
MyMsgObject myGlobalObject;

void MethodWrapperShowMsg(char[] Msg)
{
    // method pointer is global,
    // your objects must be used as globals:
    myGlobalObject.ShowMsg(Msg);
}

// declare function pointer ("functor"),
// syntax is weird

typedef
    void (*MyGlobalFunctorType) (char[] Msg);

void main()
{
    // declare function pointer variable
    MyGlobalFunctorType MyGlobalFunctorVar = null;

    // test function pointer variable with global function
    MyGlobalFunctorVar = &GlobalShowMsg;
    MyGlobalFunctorVar("Hello Earth");

    // instantiate class into an object variable
    myGlobalObject = new MyMsgObject();

    // test function pointer variable with wrapper function
    MyGlobalFunctorVar = &MethodWrapperShowMsg;
    MyGlobalFunctorVar("Hello Moon");
} // void main(...)

Приветствие.

0 голосов
/ 27 июня 2011

Если GetObject() может возвращать разные типы, то вам нужно будет работать с шаблонами.Примерно так:

template <class T>
int Foo(const T &o) {
    return o->GetValue(x, y);
}

int Bar() {
    return Foo(GetObject());
}

Это в основном полиморфизм времени компиляции

EDIT : если вам нужно указать, какую функцию вызывать какну, тогда вы можете сделать что-то вроде этого:

template <class T, int (T::*F)(int,int)>
int Foo(const T &o) {
    return (o->*F)(x, y);
}

int Bar() {
    // there is probably some template magic you can do to avoid knowing "Type" here..
    return Foo<Type, &Type::GetValue>(GetObject());
}

РЕДАКТИРОВАТЬ : к чему это сводится, вы можете написать код, подобный этому:

#include <iostream>

struct A {
    int GetValue(int x, int y) {
        return 42;
    }
};

struct B {
    int GetValue(int x, int y) {
        return 123;
    }
};

template <class T, int (T::*F)(int,int)>
int Foo(T &o) {
    return (o.*F)(0, 1);
}

int main() {
    A a;
    B b;
    std::cout << Foo<A, &A::GetValue>(a) << std::endl;
    std::cout << Foo<B, &B::GetValue>(b) << std::endl;
}

типы A и B не связаны, но я могу передать общий обработчик обоим.Вопрос в том, зачем это нужно?Почему бы просто не сделать что-то вроде этого (избежать всего беспорядка):

#include <iostream>

struct A {
    int GetValue(int x, int y) {
        return 42;
    }
};

struct B {
    int GetValue(int x, int y) {
        return 123;
    }
};

int Foo(int x) {
    return x
}

int main() {
    A a;
    B b;
    std::cout << Foo(a.GetValue()) << std::endl;
    std::cout << Foo(b.GetValue()) << std::endl;
}

Я не вижу, что вы можете получить, имея тип, объект и функцию для вызова, все определяется шаблоном,может просто сделать это напрямую или, возможно, с несколькими простыми тонкими обертками.

Кроме того, почему бы просто не иметь все типы, которые могут быть возвращены с помощью GetObject, использовать общий интерфейс, от которого они наследуются,так вы можете просто использовать виртуальные функции, как они были предназначены?Это имеет «кодовый запах» ...

0 голосов
/ 27 июня 2011

Ваш Foo должен также взять указатель на объект класса T:

typedef int (T::MyMemFun*)(int, int);
void Foo(MyMemFun f, T * t)
{
    ...
    res = t->*f(x, y);
    ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...