как получить адрес метода объекта внутри другого метода
От: romamoramento  
Дата: 21.01.03 09:22
Оценка:
привет, вот такая проблема — хочеться написать что-то типа

Исправлена подсветка синтаксиса. -- ПК.

class abc {
public:
    start {
      void* ptr = this->action;
      }
    action ();    
  }


но это не компилируется, я что-то слышал о том,
что передаваемый this — это неявный указатель.
Почему адрес свойства объекта я могу получить
во время исполнения, а адрес метода нет?

может есть какие либо обходные методы решения?

спасибо, Роман.
Re: как получить адрес метода объекта внутри другого метода
От: Сергей Зизев Украина  
Дата: 21.01.03 09:33
Оценка: 3 (1)
Здравствуйте, romamoramento, Вы писали:

R>привет, вот такая проблема — хочеться написать что-то типа

R>class abc {
R>public:
R>    start { // Это еще что такое ? 
R>      void* ptr = this->action;
R>      }
R>    action ();    
R>  }


Тип указателя ptr не соответствует типу присваемого ему значения.
Тип функции action void (abc::*ptr_to_action_function)()
class abc 
{ 
public: 
  typedef void (abc::*ptr_to_action_function)();
  void start()
  { 
    ptr_to_action_function ptr = action; 
    // (this->*ptr)(); // Вызов
  } 
  void action(); 
};


R>но это не компилируется, я что-то слышал о том,

R>что передаваемый this — это неявный указатель.
R>Почему адрес свойства объекта я могу получить
R>во время исполнения, а адрес метода нет?

R>может есть какие либо обходные методы решения?


R>спасибо, Роман.
Re: как получить адрес метода объекта внутри другого метода
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 21.01.03 09:34
Оценка:
Здравствуйте, romamoramento, Вы писали:

class A
{
public:
    void start()
    {
        void (A::*ptr)() = action;
    }
    
    void action ()
    {}
};


Почитай про "указатели на члены".
... << RSDN@Home 1.0 beta 4 >>
Re[2]: как получить адрес метода объекта внутри другого мето
От: romamoramento  
Дата: 21.01.03 11:36
Оценка:
Здравствуйте, Сергей Зизев, Вы писали:
СЗ>Тип указателя ptr не соответствует типу присваемого ему значения.
СЗ>Тип функции action void (abc::*ptr_to_action_function)()

дело не в этом, вот другой, консольный пример,
всё, что написано в функции main работает,
а в классе ptr=&data; работает, а ptr=&action; — нет
я понимаю всю опасность получения подобных адресов,
но всё-таки не понятно, почему адрес свойства можно получить
как и для глобальной переменной, а адрес функции класса нет?
спасибо, Роман.

Исправлена подсветка синтаксиса. -- ПК.

class abc {
public:
    int data;
    void action () { }
    void func () {
        void *ptr;
        ptr=&data;
        ptr=&action; //не работает
        }
    };

int glob_data;
void glob_action () { }

void main () {
void *ptr;
ptr = &glob_data;
ptr = &glob_action;
}
Re[3]: как получить адрес метода объекта внутри другого мето
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 21.01.03 11:50
Оценка:
Здравствуйте, romamoramento, Вы писали:

R>но всё-таки не понятно, почему адрес свойства можно получить

R>как и для глобальной переменной, а адрес функции класса нет?

А зачем это надо?
... << RSDN@Home 1.0 beta 4 >>
Re[3]: как получить адрес метода объекта внутри другого мето
От: Павел Кузнецов  
Дата: 21.01.03 11:51
Оценка: 4 (1)
Здравствуйте, romamoramento, Вы писали:

R>всё, что написано в функции main работает,

R>а в классе ptr=&data; работает, а ptr=&action; — нет

R>
R>class abc {
R>public:
R>    int data;
R>    void action () { }
R>    void func () {
R>        void *ptr;
R>        ptr=&data;
R>        ptr=&action; //не работает
R>


Правильный синтаксис &abc::action; результат этой операции — так называемый указатель на член. Присвоить его переменной типа void* нельзя, хотя бы потому что sizeof(&abc::action) в общем случае не равен sizeof(void*). Читать об указателях на члены.

R>
R>int glob_data;
R>void glob_action () { }

R>void main () {


Должно быть:

int main() {


R>
R>void *ptr;
R>ptr = &glob_data;
R>ptr = &glob_action;


То, что твой компилятор позволяет подобные вещи — его "персональный" выбор, стандарт не гарантирует возможность подобных преобразований.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: как получить адрес метода объекта внутри другого мето
От: warlockonline Россия  
Дата: 21.01.03 11:51
Оценка:
Здравствуйте, romamoramento, Вы писали:

R>но всё-таки не понятно, почему адрес свойства можно получить

R>как и для глобальной переменной, а адрес функции класса нет?

Переменная класса содержит только его переменные-члены.
Вызов функции класса происходит почти как вызов обыкновенной функции, и компилятор добавляет первый, "невидимый" для нас параметр CClass* this, с помощью которого можно обращаться к полям данных нужной нам переменной типа CClass.

Поэтому мы и не можем получить указатель на функцию-член класса стандартными способами.
Re[3]: как получить адрес метода объекта внутри другого мето
От: Сергей Зизев Украина  
Дата: 21.01.03 11:57
Оценка:
Здравствуйте, romamoramento, Вы писали:

R>Здравствуйте, Сергей Зизев, Вы писали:

СЗ>>Тип указателя ptr не соответствует типу присваемого ему значения.
СЗ>>Тип функции action void (abc::*ptr_to_action_function)()

R>дело не в этом, вот другой, консольный пример,

R>всё, что написано в функции main работает,
R>а в классе ptr=&data; работает, а ptr=&action; — нет
R>я понимаю всю опасность получения подобных адресов,
R>но всё-таки не понятно, почему адрес свойства можно получить
R>как и для глобальной переменной, а адрес функции класса нет?
R>спасибо, Роман.

R>


R>
class abc {
R>public:
R>    int data;
R>    void action () { }
R>    void func () {
R>        void *ptr;
R>        ptr=&data;
R>        ptr=&abc::action; //Такие преобразования вообще недопустимы, тем более, 
//что action не является статическим членом класса. Если ты хочешь все таки работать с методом косвенно, то смотри мой первый ответ
R>        }
R>    };

R>int glob_data;
R>void glob_action () { }

R>int main () {
R>void *ptr;

R>ptr = &glob_data;
Это преобразование тоже неверно, т.к. у тебя нет никакой гарантии, что размер адреса функции будет совпадать с размером указателя 
R>ptr = &glob_action;
R>}
Re[3]: как получить адрес метода объекта внутри другого мето
От: Андрей Тарасевич Беларусь  
Дата: 21.01.03 16:53
Оценка: 26 (3)
Здравствуйте, romamoramento, Вы писали:

СЗ>>Тип указателя ptr не соответствует типу присваемого ему значения.

СЗ>>Тип функции action void (abc::*ptr_to_action_function)()

R>дело не в этом, вот другой, консольный пример,

R>всё, что написано в функции main работает,
R>а в классе ptr=&data; работает, а ptr=&action; — нет
R>я понимаю всю опасность получения подобных адресов,
R>но всё-таки не понятно, почему адрес свойства можно получить
R>как и для глобальной переменной, а адрес функции класса нет?

Адрес поля объекта можно тоже получить двумя способами. Если в классе 'A' есть поле 'f' типа 'int', то выражение '&f' на территории какого-нибудь метода класса 'A' или выражение '&(A::f)' (скобки важны) будет давать "обычный" указатель на это поле — типа 'int*'. Это указатель можно привести к типу 'void*'. А вот выражение '&A::f' будет давать указатель типа "указатель на член класса" — тип 'int A::*'. Это указатель нельзя привести к типу 'void*'.

Это все отностится к полям классов. Что касается нестатических методов классов, то указатели на них можно получить только одним способом — как указатели типа "указатель на член класса". Если в классе 'A' есть метод 'int m(double)', то выражение '&A::m' будет давать указатель типа 'int (A::*)(double)'. Этот указатель не может быть приведен к типу 'void*'.

То, что написано в твоем изначальном коде — полная ерунда. Получить указатель на нестатический метод класса можно только при помощи явного применения оператора '&' и с указанием полностью квалифицированного имени метода '&<имя класса>::<имя метода>'.

P.S. 'romamoramento' — это что, поклонник Mylene Farmer?
Best regards,
Андрей Тарасевич
Re[3]: как получить адрес метода объекта внутри другого мето
От: romamoramento  
Дата: 22.01.03 07:30
Оценка:
привет,
спасибо всем кто помог разобраться, кстати этот консольный пример
компилируется на билдере и вижуал, и адрес _метода класса_ можно
тоже получить как void*, указав метод как static.
лично я понимаю void* как указатель на что-то — т.е. адрес,
а он должен быть у любого поля и функции.
Ещё раз спасибо, миленофан Роман.
Re[4]: как получить адрес метода объекта внутри другого мето
От: Gadsky Россия  
Дата: 22.01.03 07:36
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:

R>>
R>>void main () {


ПК>Должно быть:


ПК>
int main() {


Павел, а почему main должна быть int? Это стандарт? Я вроде все время void использую, но это под VC.
Re[4]: как получить адрес метода объекта внутри другого мето
От: Аноним  
Дата: 22.01.03 07:41
Оценка:
Здравствуйте, romamoramento, Вы писали:

R>лично я понимаю void* как указатель на что-то — т.е. адрес,

R>а он должен быть у любого поля и функции.

void* — это нетипизированный указатель на данные.
Смешивать его с указателями на код нельзя не только по смыслу, но и в силу того, что существуют архитектуры, где адреса данных имеют иную природу, нежели адреса кода (т. е. память для данных отдельна и отлична от памяти для кода).
Re[5]: как получить адрес метода объекта внутри другого мето
От: Михаил Можаев Россия www.mozhay.chat.ru
Дата: 22.01.03 07:52
Оценка:
Здравствуйте, Gadsky, Вы писали:

G>Павел, а почему main должна быть int? Это стандарт? Я вроде все время void использую, но это под VC.


Прошу прощения, что вмешиваюсь ,но:

C++ Standard, 3.6.1/2

An implementation shall not predefine the main function. This function shall not be overloaded. It shall
have a return type of type int, but otherwise its type is implementationdefined.
All implementations
shall allow both of the following definitions of main:

int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }

Re[5]: как получить адрес метода объекта внутри другого мето
От: Павел Кузнецов  
Дата: 22.01.03 08:02
Оценка:
Здравствуйте, Gadsky, Вы писали:

ПК>>
int main() {


G>Павел, а почему main должна быть int? Это стандарт?


Да (3.6.1/2).

G>Я вроде все время void использую, но это под VC.


Вольность последнего.
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[6]: Мелочь, а приятно :)
От: Gadsky Россия  
Дата: 22.01.03 08:11
Оценка:
День прошел не даром
Re[4]: как получить адрес метода объекта внутри другого мето
От: Андрей Тарасевич Беларусь  
Дата: 22.01.03 18:27
Оценка: 30 (1)
Здравствуйте, romamoramento, Вы писали:

R>спасибо всем кто помог разобраться, кстати этот консольный пример

R>компилируется на билдере и вижуал, и адрес _метода класса_ можно
R>тоже получить как void*, указав метод как static.
R>лично я понимаю void* как указатель на что-то — т.е. адрес,
R>а он должен быть у любого поля и функции.

Адрес и указатель — разные вещи. Указатель в общем случае — это больше чем адрес. В С++ существует несколько категорий указателей:

1. указатели на "самостоятельные" данные (включая "обычные" указатели на поля классов)

struct A 
{ 
  int i; 
  void foo(); 
  static int bar(double);
};

A a;
int i;

void foo();


int* p = &i;
int* q = &a.i;


2. указатели на "самостоятельные" функции (включая статические методы классов)

void (*p)() = &foo;
int (*q)(double) = &A::bar;


3. указатели на нестатические методы классов (указатели типа "указатель на член класса")

void (A::*p)() = &A::foo;


4. указатели на нестатические поля классов (указатели типа "указатель на член класса")

int A::*p = &A::i;


Указатели в этих группах в С++ имеют разную природу и приведения типов между группами в С++ невозможно. Что там тебе позволяет делать компилятор никакого значения не имеет — все равно легальным С++ это не будет и, в конце концов, добром не кончится.

В твоем случае указатель типа 'void*' является указателем первой группы. Укзатель на статический метод — указатель второй группы. Приведение типа между этими типами невозможно.
Best regards,
Андрей Тарасевич
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.