имея "typedef void FuncCharPtr" в одном классе, как передать функцию, которая использует этот typedef с нестатическими функциями? - PullRequest
0 голосов
/ 29 января 2011

Итак, у меня есть класс вроде:

class IGraphElement{

    // We should define prototype of functions that will be subscribers to our data
    typedef void FuncCharPtr(char*, int) ;

public:
    // Function for adding subscribers functions
    void Add(FuncCharPtr* f)
    {
            //...
    }
 };

и другой класс, например

#include "IGraphElement.h"

class  simpleRendererGraphElement : public IGraphElement
{
  public:
    IGraphElement* charGenerator;
    // we owerrite init
    void Init(IGraphElement* CharGenerator)
    {
        charGenerator = CharGenerator;
        //we can to subscribe some function to our data generator
        charGenerator->Add(renderCastedData); // and here we receive C3867 
    }
    void renderCastedData(char* castedChar, int castedCharLength) //  our event system receives functions declared like void FuncCharPtr(char*, int) ;
    { }
};

, почему мы получаем ошибку C3867 и как ее исправить, не делая функции статичными?

Ответы [ 3 ]

1 голос
/ 29 января 2011

renderCastedData - нестатическая функция-член.Его тип

void (simpleRendererGraphElement::*)(char*, int)

Чтобы вызвать его, вам нужно иметь экземпляр simpleRendererGraphElement для параметра this.Есть много решений этой проблемы.Один из вариантов - сделать Add шаблоном функции, который принимает все, что может быть вызвано с параметром char* и int:

template <typename Function>
void Add(Function f)

, тогда вы можете написать объект функции для переносаВызов:

struct RenderCastedDataFunctor
{
    simpleRendererGraphElement* obj_;

    RenderCastedDataFunctor(simpleRendererGraphElement* obj)
        : obj_(obj) { }

    void operator()(char* castedChar, int castedCharLength)
    {
        obj_->renderCastedData(castedChar, castedCharLength);
    }
};

и из вашей функции Init вы можете вызывать

charGenerator->Add(RenderCastedDataFunctor(this));

(библиотеки bind и function из Boost, C ++ TR1 и C ++0x предоставляет обобщенную форму этого шаблона, позволяя вам связывать аргументы с любой вызываемой сущностью и сохранять эти связанные вызываемые сущности для последующего использования. Этот конкретный подход здесь представляет собой просто упрощенную версию, которая должна работать без каких-либо дополнительных или, возможно, не поддерживаемых библиотек.)

1 голос
/ 29 января 2011

Функция-член не является обычной функцией и не может быть назначена обычному указателю на функцию.

Используйте статическую функцию-член, если renderCastedData не нужно привязывать к какому-либо экземпляру класса.

Если renderCastedData должен быть привязан к экземпляру класса, пусть IGraphElement::Add принимает указатель на функцию-член и указатель на класс.

boost :: function и boost :: bind также являются хорошим выбором для этой проблемы, они обеспечивают гораздо большую гибкость, но иногда это может быть немного медленнее.

1 голос
/ 29 января 2011
typedef void FuncCharPtr(char*, int) ;

Прежде всего, выше должно быть следующее:

typedef void (*FuncCharPtr)(char*, int) ;

Во-вторых, renderCastedData не является указателем функции;это указатель на функцию-член.Так что есть разница.Это тип void (simpleRendererGraphElement::*)(char*, int);, а не тип выше!

...