Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Вопрос по указательям на функции 
:(
    Опции темы
knut
Дата 20.4.2007, 15:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 7.2.2006

Репутация: нет
Всего: нет



добрый день
вот вопрос у меня такой(не совсем извращенныйsmile)
реально ли такое. 
функцию-член присвоить указатель на виртуальный метод предка, а потом вызвать её на экземпляре потомка
Можно ли ли так вообще делать и если не то почему?
ну что то примерно такое

Код


class cBase
{
public:
  virtual void f() { };
 };

class cBase : public cDer
{
public:
  virtual void f() {};
 };

typedef void (cBase::*VirtualFunctionPointer) ();


  cBase a;
  cDer  b;
  cDer* pb = &b;

  VirtualFunctionPointer p = &cBase::f;

  (pb->*p) ();

  p = &cBase::g;
  (pb->*p) ();




--------------------
Цитата

Многие вещи нам непонятны не оттого, что наши понятия слабы, а оттого, что данные вещи не входят в круг наших понятий.
PM MAIL   Вверх
HappyLife
Дата 20.4.2007, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 642
Регистрация: 17.5.2006

Репутация: 3
Всего: 8



Я не догнал чего ты хочешь.
Тем более не понимаю к чему ты делаешь два класса cBase и что за &cBase::g; вот это вот Г.
PM MAIL   Вверх
Vyacheslav
Дата 20.4.2007, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



Я тоже не понял. Особенно
насчет
Код

class cBase {
class cBase : public cDer {


но могу сказать
что 
Код

typedef void (cBase::*BaseVirtualFunctionPointer) ();
typedef void (cDerived::*DerivedVirtualFunctionPointer) ();

это своершенно разные типы и указатель на метод производного класса тебе не удастся присвоить указателю на метод базового класса. К сожалению :(

Добавлено через 7 минут и 9 секунд
Дополнительно пример из хелпа по С++Builder, с помощью которого поясняется, зачем разработчики ввели ключевое слово __closure
Код

class base

{
  public:
    void func(int x) { };
};
typedef void (base::* pBaseMember)(int);

class derived: public base

{
  public:
    void new_func(int i) { };
};

int main(int argc, char* argv[])
{
  derived         derivedObject;
  pBaseMember m = &derived::new_func; // ILLEGAL
  return 0;
}





--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
knut
Дата 20.4.2007, 16:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 7.2.2006

Репутация: нет
Всего: нет



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



--------------------
Цитата

Многие вещи нам непонятны не оттого, что наши понятия слабы, а оттого, что данные вещи не входят в круг наших понятий.
PM MAIL   Вверх
Anikmar
Дата 20.4.2007, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



А можно поподробнее саму задачу описать?
Т.е. в наследнике у нас есть указатель. Ему присваиваем адрес метода базового класса. Потом наследник вызывает этот метод через этот указатель.
Вызывается метод базового класса, а так как он виртуальный - то по переданному ему адресу объекта потомка он вызывает необходимую функцию потомка. Правильно я понял?
PM MAIL ICQ   Вверх
Vyacheslav
Дата 20.4.2007, 17:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 9
Всего: 59



И никак иначе? Тяжело с Вами.
Я понимаю, что торг не уместен, но может это спасет отца русской демократии smile
Код

 cDer  b;
 b.cBase::f();

 сDer* pb = &b
 b->cBase::f();



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
Earnest
Дата 20.4.2007, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Цитата(knut @  20.4.2007,  17:14 Найти цитируемый пост)
мне надо зделать если возможно такое т.е
указателю на функцию-член присвоить указатель на виртуальный метод предка, а потом вызвать её на экземпляре потомка

Мне кажется, это зависит от компилятора. Если он присваивает указателю адрес конкретной функции (предка), то фиг вам. А если адрес специального стабика, где выполняется переадресация, то запросто. Не в курсе, что написано в стандарте. Знаю только, что MSVC это делает. Т.е. указатель, которому присвоен "адрес" виртуальной функции предка, при подстановке this потомка вызовет правильную функцию. А вот старый борланд (еще досовских времен) - нет. Что борланд делает сейчас - не знаю.



--------------------
...
PM   Вверх
Anikmar
Дата 20.4.2007, 21:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Цитата(Earnest @  20.4.2007,  20:34 Найти цитируемый пост)
Мне кажется, это зависит от компилятора. Если он присваивает указателю адрес конкретной функции (предка), то фиг вам. А если адрес специального стабика, где выполняется переадресация, то запросто. Не в курсе, что написано в стандарте. Знаю только, что MSVC это делает. Т.е. указатель, которому присвоен "адрес" виртуальной функции предка, при подстановке this потомка вызовет правильную функцию. А вот старый борланд (еще досовских времен) - нет. Что борланд делает сейчас - не знаю.

Блин, а я думал, что если метод класса обычный - то адрес его определяется линковкой, а если виртуальный - то во время исполнения, при помощи таблицы виртуальных методов... Соответственно, если указатель будет указывать на виртуальный метод базового класса, но в момент вызова ему будет передан адрес объекта-потомка, то все должно нормально сработать - по адресу объекта будет определен тип, найдена функция для этого типа и вызвана...
PM MAIL ICQ   Вверх
Earnest
Дата 20.4.2007, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

Репутация: 53
Всего: 183



Сам подумай, что такое адрес функции-члена? Это просто адрес. Откуда при вызове по этому адресу возьмется информация о полиморфизме? 
Когда компилятор видит в коде вызов виртуальной функции, он не подставлет ее адрес непосредственно, а делает промежуточную переадресацию: из объекта выковыривается адрес vtable, из vtable по номеру берем адрес реально-вызываемой функции. Вот тебе и полиморфизм. А если мы присваиваем указателю адрес, то адрес чего?

MSVC выкручивается просто: и в первом и во втором случае (т.е. и при вызове виртуальной функции, и при использовании ее адреса) генерит небольшой стаб, где выполняет вышеописанную переадресацию. А в качестве адреса выдает адрес этого самого стаба. В результате получается, что как бы ты не использовал  виртуальную функцию, реально ты получаешь адрес стаба. Именно поэтому все всегда виртуально работает.




--------------------
...
PM   Вверх
Anikmar
Дата 20.4.2007, 21:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2513
Регистрация: 26.11.2006
Где: Санкт-Петербург

Репутация: 9
Всего: 59



Earnest, Да, конечно, я ступил. Я подумал об адресе объекта, а не об адресе метода. 

Бывает... 

Век живи - век учись.
И все равно дураком помрешь...
PM MAIL ICQ   Вверх
knut
Дата 21.4.2007, 14:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 588
Регистрация: 7.2.2006

Репутация: нет
Всего: нет



Цитата

Мне кажется, это зависит от компилятора. Если он присваивает указателю адрес конкретной функции (предка), то фиг вам. А если адрес специального стабика, где выполняется переадресация, то запросто. Не в курсе, что написано в стандарте. Знаю только, что MSVC это делает. Т.е. указатель, которому присвоен "адрес" виртуальной функции предка, при подстановке this потомка вызовет правильную функцию. А вот старый борланд (еще досовских времен) - нет. Что борланд делает сейчас - не знаю.

Vyacheslav
Цитата

это своершенно разные типы и указатель на метод производного класса тебе не удастся присвоить указателю на метод базового класса. К сожалению :(

Так работает smile
Код

class A
   {
   virtual void f ()  = 0;
   };

class B : public A
   {
public:
   void f ()
      {
      std::cout << "B\n";
      }
   };

class C : public A
   {
public:
   void f ()
      {
      std::cout << "C\n";
      }
   };
//  и собственно и вызовы функции

int main()
{

 typedef void (A::*VirtualFunctionPointer) ();
   VirtualFunctionPointer pmfn = &A::f;

   B b;
   C c;
   (b.*pmfn) ();
   (c.*pmfn) ();
return 0;
}






--------------------
Цитата

Многие вещи нам непонятны не оттого, что наши понятия слабы, а оттого, что данные вещи не входят в круг наших понятий.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1042 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.