Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

C++

Войти
Регистрация
Восстановить пароль
 
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
#1

Указатель на метод класса в качестве аргумента метода класса - C++

20.03.2015, 15:21. Просмотров 553. Ответов 14
Метки нет (Все метки)

Функция _createFun вызывается для создания ХХХ в основном классе. Но вот потребовалось создать ХХХ в дополнительном классе. Вопрос: как передать указатель на МЕДОТ класса One в качестве аргумента класса Two? Конечно можно передать указатель на объект _world в класс Two и в него скопировать функцию _createFun, но это не лучший для меня вариант, в том случае, если существует возможность передавать указатель на метод.

Код набросал для наглядности.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class XYZ // Какой-то там класс
{
public:void Create();
};
 
struct ABC 
{
    int a;
};
 
class Two // Дополнительный класс
{
private:
    ABC* _ptrStruct;
 
public:
    VOID Create( ABC* (*fun)(int a, int b) )
    {
        _ptrStruct = fun( 2, 5 );
    }
 
};
 
class One // Основной класс
{
private:
    XYZ* _world; // Этот объект создаётся в этом классе, 
    // и его выполнение лежит в методе _createFun который и нужно передеать в дополнительный класс
    Two _two;
 
    ABC* _createFun( int a, int b )
    {
        //...
        _world->Create();
        //...
    }
public:
    VOID Load()
    {
        _world = new XYZ;
        _two.Create( &_createFun );
    }
 
};
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
20.03.2015, 15:21
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Указатель на метод класса в качестве аргумента метода класса (C++):

Указатель на метод класса. - C++
Программа отказывается присваивать метод класса указателю. Как исправить? test.cpp: In function ‘int main()’: test.cpp:66: error:...

Передача функции-члена в качестве аргумента (не через указатель) - C++
Привет! Озадачился такой проблемой - вот пример того, что нужно typedef void(class1::*method)(); void func (method) {}; func...

callback метода класса - C++
Предыстория: нужно последовательно запускать несколько однотипных циклов большой степени вложенности, в теле которых вызывать разные...

Запуск метода класса в новом потоке - C++
Здравствуйте, у меня есть класс, в нём функция - необходимо вызвать эту функцию в нескольких потоках, возможно ли это?

Явная специализация метода для типа шаблонного класса - C++
Добрый вечер, уважаемые знатоки! :) Хочу задать вопрос по созданию шаблонов. В общем, пусть у меня есть шаблон некоторого класса: ...

Надо переделать метод класса. - C++
Есть программа, надо переделать метод класса. Все - в описании. #include <iostream> using namespace std; class Complex { ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
rao
853 / 406 / 119
Регистрация: 02.04.2014
Сообщений: 1,171
20.03.2015, 17:28 #2
Непонятно каким боком _world затесался в функцию-параметр? Что она там делает?
Ну да ладно. Попробуй через интерфейс:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct iFactory
{
    virtual theABC* CreateSomething(int a, int b);
};
 
class CMaster
{
private:
    theABC* _ptrStruct;
public:
    VOID Create( iFactory * pCreator )
    {
        _ptrStruct = pCreator->CreateSomething(2,5);
    }
};
 
class CSlave: public iFactory
{
    CMaster _two;
 
    theABC* CreateSomething( int a, int b )
    {
        return new theABC;
    }
    VOID Load()
    {
        _two.Create( this );
    }
};
1
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
20.03.2015, 18:03  [ТС] #3
На тестовом коде всё прошло хорошо, теперь буду пробовать в основной код всё это дело интегрировать. Спасибо.
0
Avazart
Эксперт С++
7192 / 5366 / 280
Регистрация: 10.12.2010
Сообщений: 23,674
Записей в блоге: 17
20.03.2015, 18:36 #4
Цитата Сообщение от _Ryuzaki13_ Посмотреть сообщение
но это не лучший для меня вариант, в том случае, если существует возможность передавать указатель на метод.
Указатель на метод можно использовать только относительно какого либо объекта.

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
 
 
class A
{
    public:
        void x() { std::cout<<"x()"<<std::endl; }
        void y() { std::cout<<"y()"<<std::endl; }
};
 
typedef void(A::*Method)();
 
class B
{
    public:
        B():method_(0),object_(0){};
 
        void setMethod(A* object,Method method)
        {
            object_= object;
            method_= method;
        }
 
        void invoke()
        {
            if(object_ && method_)
             (object_->*method_)();
        }
 
    private:
        Method method_;
        A* object_;
};
 
int main()
{
     A a;
     B b;
 
     b.setMethod(&a, A::x );
     b.invoke();
 
     b.setMethod(&a, A::y );
     b.invoke();
 
    getchar();
    return 0;
}
0
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
20.03.2015, 18:41  [ТС] #5
Цитата Сообщение от rao Посмотреть сообщение
Непонятно каким боком _world затесался в функцию-параметр? Что она там делает?
Ну да ладно. Попробуй через интерфейс:


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
struct iFactory
{
* * virtual theABC* CreateSomething(int a, int b);
};
class CMaster
{
private:
* * theABC* _ptrStruct;
public:
* * VOID Create( iFactory * pCreator )
* * {
* * * * _ptrStruct = pCreator->CreateSomething(2,5);
* * }
};
class CSlave: public iFactory
{
* * CMaster _two;
theABC* CreateSomething( int a, int b )
* * {
* * * * return new theABC;
* * }
* * VOID Load()
* * {
* * * * _two.Create( this );
* * }
};
В конечном итоге он мне выдаёт ошибку о неразрешённых внешних символов.


C++
1
2
3
4
5
struct iBox2DCreate
{
    virtual b2Body* _addCircle( float x, float y, float r, bool dyn = true );
    virtual b2Body* _addRect( float x, float y, float w, float h, bool dyn = true );
};
Метод класса
C++
1
2
3
4
5
6
7
public:
WGS_API VOID Create( wgGraphicsDX11Ptr _gdx11, iBox2DCreate* _addToWorld )
{
...
_bodySmall = _addToWorld->_addCircle( 0.0f, 0.0f, 2.0f, true );
... 
}

Методы _addCircle и _addRect реализованы в основном классе (public), ": public iBox2DCreate" естественно не пропустил.

error LNK2001: неразрешенный внешний символ ""public: virtual class b2Body * __cdecl WGS::iBox2DCreate::_addCircle(float,float,float,bool)" (?_addCircle@iBox2DCreate@WGS@@UEAAPEAVb2Body@@MMM_N@Z)"
0
Avazart
Эксперт С++
7192 / 5366 / 280
Регистрация: 10.12.2010
Сообщений: 23,674
Записей в блоге: 17
20.03.2015, 18:48 #6
rao, Виртуальный деструктор забыл.
_Ryuzaki13_, Не используйте префиксное подчеркивание в именах, плохой тон.
0
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
20.03.2015, 18:58  [ТС] #7
Цитата Сообщение от Avazart Посмотреть сообщение
rao, Виртуальный деструктор забыл.
_Ryuzaki13_, Не используйте префиксное подчеркивание в именах, плохой тон.
Не знал, и исправить как я понял уже никак.

Деструктор добавил, но изменений 0.

Впринципе здесь я понимаю что сам где-то накосячил, т.к такой код добавляю в любой файл проекта и компилятор не жалуется

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class XYZ
{
public:
    void Create();
};
 
struct theABC 
{
    int a;
};
 
 
struct TEST
{
    virtual theABC* _createFun( int a, int b );
};
 
class Two
{
private:
    theABC* _ptrStruct;
 
public:
    VOID Create( TEST* t )
    {
        _ptrStruct = t->_createFun( 2, 5 );
    }
 
};
 
class One : public TEST
{
private:
    XYZ* _world;
    Two _two;
 
    theABC* _createFun( int a, int b )
    {
        //...
        _world->Create();
        //...
    }
public:
    VOID Load()
    {
        _two.Create( this );
    }
 
};
0
Avazart
Эксперт С++
7192 / 5366 / 280
Регистрация: 10.12.2010
Сообщений: 23,674
Записей в блоге: 17
20.03.2015, 19:00 #8
Может подтолкнет Паттерн Factory Method (фабричный метод)
0
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
20.03.2015, 19:21  [ТС] #9
Цитата Сообщение от Avazart Посмотреть сообщение
Может подтолкнет Паттерн Factory Method (фабричный метод)
Тоже не то.

Я кажется начинаю понимать, почему он ругается на неразрешённые символы.

Главный класс (далее класс А) является абстрактным. Все эти классы у меня реализованы в библиотеке dll.

функция main в .exe приложении создаётся объект B который является дочерним(вроде бы так) от объекта А, в объекте А методы экспортируются _declspec(dllexport), в то время объект А порождён от виртуальной структуры C

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// DLL
struct C
{
    virtual b2Body* _addCircle( float x, float y, float r, bool dyn = true );
    virtual b2Body* _addRect( float x, float y, float w, float h, bool dyn = true );
};
 
// DLL
class A : public C
{
...
_declspec(dllexport)  b2Body* _addCircle( float x, float y, float r, bool dyn) {...};
_declspec(dllexport) b2Body* _addRect( float x, float y, float w, float h, bool dyn) {...};
...
}
 
// EXE
class B : public A
{...}
Вполне можно предположить, что он не может экспортировать методы виртуального класса из DLL в EXE, хотя в А они экспортируемые.
0
Avazart
Эксперт С++
7192 / 5366 / 280
Регистрация: 10.12.2010
Сообщений: 23,674
Записей в блоге: 17
20.03.2015, 19:34 #10
Цитата Сообщение от _Ryuzaki13_ Посмотреть сообщение
Вполне можно предположить, что он не может экспортировать методы виртуального класса из DLL в EXE, хотя в А они экспортируемые.
Ну так... классы и DLL это вообще бее....
0
_Ryuzaki13_
1 / 1 / 1
Регистрация: 20.03.2015
Сообщений: 12
20.03.2015, 19:50  [ТС] #11
Хотя с другой стороны компилятор говорит что ошибка именно в dll проекте а не ехе.
Сначала создаётся .lib и .exp и затем ошибка.
Немного потыкал, понятно что класс-наследник не может получить доступ к родительским методам, но вот почему

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct C
{
    virtual int* _addCircle( float x, float y, float r, bool dyn );
    virtual int* _addRect( float x, float y, float w, float h, bool dyn );
};
 
class A : public C
{
...
_declspec(dllexport) int* _addCircle( float x, float y, float r, bool dyn);
_declspec(dllexport) int* _addRect( float x, float y, float w, float h, bool dyn);
...
}
 
int* A::_addCircle( float x, float y, float r, bool dyn)
{
...
}
 
int* A::_addRect( float x, float y, float w, float h, bool dyn)
{
...
}
 
неразрешенный внешний символ ""public: virtual class int * __cdecl C::_addCircle(float,float,float,bool)" (?_addCircle@C@WGS@@UEAAPEAVb2Body@@MMM_N@Z)"
А не получает С

Добавлено через 5 минут
Смех один, всего навсего класс надо было сделать чисто виртуальным

C++
1
2
3
4
5
struct C
{
    virtual int* _addCircle( float x, float y, float r, bool dyn ) = 0;
    virtual int* _addRect( float x, float y, float w, float h, bool dyn ) = 0;
};
0
Fulcrum_013
721 / 746 / 73
Регистрация: 14.12.2014
Сообщений: 5,909
Завершенные тесты: 3
15.04.2015, 00:00 #12
Цитата Сообщение от _Ryuzaki13_ Посмотреть сообщение
Вопрос: как передать указатель на МЕДОТ класса One в качестве аргумента класса Two?
для этого существуют __closure указатели
0
Avazart
15.04.2015, 10:37
  #13

Не по теме:

Цитата Сообщение от Fulcrum_013 Посмотреть сообщение
для этого существуют __closure указатели
Это чисто прибабаха C++Builder

0
Fulcrum_013
15.04.2015, 17:01
  #14

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
для этого существуют __closure указатели
Это чисто прибабаха C++Builder
в остальных компиляторах просто структуру
C++
1
struct __closure{void *Data, void* Code}
делать и обрабатывать приходится ручкам

0
Avazart
Эксперт С++
7192 / 5366 / 280
Регистрация: 10.12.2010
Сообщений: 23,674
Записей в блоге: 17
15.04.2015, 17:07 #15
Есть std::function / boost::function, нечего городить.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.04.2015, 17:07
Привет! Вот еще темы с ответами:

Передача в новый поток в качестве аргумента string - C++
хелп:wall: Пытаюсь передать аргумент так: DWORD potoc(char * args) { const char * ta = static_cast &lt;const char *&gt; (args); } ...

Замена экземпляра структуры для подачи в качестве аргумента - C++
Интересует есть ли способ замены экземпляра структуры для подачи в функцию. Т.е. если я создаю собственную структуру(естественно с...

Как не писать один и тот же код, для функции, принимающей разные типы данных в качестве аргумента - C++
Проблема такая: есть некая функция. Внутри нее происходят одни и теже вычисления, вне зависимости от типа входных данных. void...

Указатель на метод - C++
struct abc{ int a; int b; int c; abc(int na = 0, int nb = 0, int nc = 0):a(na),b(nb),c(nc){}; bool conf(int d){ ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
15.04.2015, 17:07
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru