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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Трюк, возможно ли это? 
:(
    Опции темы
vaddsm
  Дата 6.9.2008, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Есть идея, вызвать на выполнение определенный код,  после инициализации экземпляра объекта (класса) в памяти, не используя, его конструктор.

Сразу не понятно, конкретно, о чем идет речь, по этому приведу пример.

Код

class TClass2 
{

  public:

  TClass2()
  {
    
    MessageBox(0,”Some code executed”,”;)”,0);
   
  };

  ~TClass2(){};

};

class TClass1
{
 
  TClass2 Class2;

  public:

  TClass1(){};
  ~TClass1(){};
};

TClass1 *obj = new TClass1();


В приведенном примере сразу после инициализации obj появится сообщение MessageBox.
При этом конструктор класса TClass1 не задействован. Так вот хотелось бы выполнить подобное в рамках класса TClass1, да так чтобы код, например того же мессаджбокса мог оперировать с параметром.  


MessageBox(0,arg,”;)”,0);


К сожалению, подобная конструкция в c++ не разрешена:

Код


class TClass2 
{

  public:

  TClass2(char *arg)
  {
    
    MessageBox(0,arg,”;)”,0);
   
  };

  ~TClass2(){};

};

class TClass1
{
 
  TClass2 Class2(“Some code executed”);

  public:

  TClass1(){};
  ~TClass1(){};
};



Есть ли другая возможность выполнить подобное? 


PM MAIL   Вверх
Fin
Дата 6.9.2008, 01:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



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

С++ не допускает иницилизирование переменных параметрами в объявлении класса. Выход из этой ситуации для тебя, 
Код

class TClass1
{
 
  TClass2 *Class2;
  public:
  TClass1(){Class2 = new TClass2(“Some code executed”);};
  ~TClass1(){delete Class2;};
};


Это сообщение отредактировал(а) Fin - 6.9.2008, 02:06


--------------------
Пролетал мимо.
PM MAIL   Вверх
vaddsm
  Дата 6.9.2008, 03:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Так, понятно, похоже я недостаточно ясно объясни, что собственно хочу сделать. Мне необходимо добиться того, чтобы конструктор класса TClass1 не был задействован, но при инициализации экземпляра класса TClass1 выполнился код (функция) с параметром. Как реализовать данное без параметра я описал в первом примере, про то, что второй пример синтаксически неверен, я тоже написал, но в нем отражена суть того, что я хочу видеть.
PM MAIL   Вверх
Fin
Дата 6.9.2008, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



vaddsm, От того, что ты хочеш видеть, не изменяет принципы работы ООП. И синтаксиса С++. 

Сделай через статик. есть несколько минусов. Но жить будет. Если хочеш чесать левое ухо правой ногой.
Код

class TClass1
{
 
  static TClass2 Class2;
  public:
  TClass1(){};
  ~TClass1(){};
};

TClass2 TClass1::Class2("Some code executed");


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

Это сообщение отредактировал(а) Fin - 6.9.2008, 10:51


--------------------
Пролетал мимо.
PM MAIL   Вверх
mes
Дата 6.9.2008, 10:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  6.9.2008,  03:10 Найти цитируемый пост)
не необходимо добиться того, чтобы конструктор класса TClass1 не был задействован, но при инициализации экземпляра класса 

Нельзя создать объект в С++, не задействовав конструктор. Если Вы не определяете конструктора, то это делает за Вас компилятор.

Цитата(vaddsm @  6.9.2008,  03:10 Найти цитируемый пост)
второй пример синтаксически неверен, я тоже написал, но в нем отражена суть того, что я хочу видеть.

используйте список инициализации :
Код

class TClass1
{
 
  TClass2 m_obj_of_class2;
  public:
  TClass1(): m_obj_of_class2(“Some code executed”) {};
  ~TClass1(){};
};





Это сообщение отредактировал(а) mes - 6.9.2008, 10:53


--------------------
PM MAIL WWW   Вверх
vinter
Дата 6.9.2008, 10:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  6.9.2008,  04:10 Найти цитируемый пост)
чтобы конструктор класса TClass1 не был задействован


Цитата(vaddsm @  6.9.2008,  04:10 Найти цитируемый пост)
при инициализации экземпляра класса TClass1 выполнился код (функция) с параметром

не замечаешь противоречий?


--------------------
Мой блог
PM MAIL WWW   Вверх
cutwater
Дата 6.9.2008, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



 smile Афтар видит в этом магию Девида Блейна
ЗЫ: Извините не удержался.



--------------------
user posted image
PM MAIL   Вверх
vaddsm
  Дата 6.9.2008, 14:16 (ссылка)    | (голосов:4) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата


Нельзя создать объект в С++, не задействовав конструктор. Если Вы не определяете конструктора, то это делает за Вас компилятор.




Ты это к чему сказал то? Разве из моего сообщения следует, что я хочу создать ОБЪЕКТ не задействовав в этом мероприятии его КОНСТРУКТОР. Прошу перед тем, как что либо  писать, внимательно вникать в суть поставленной задачи. 

Еще раз! Мне надо выполнить код при создании объекта, но при этом недолжно быть явного использования конструктора.


Код

TClass1(): m_obj_of_class2(“Some code executed”) {}; 


Это тоже, явно противоречит тому, что я писал. Еще раз: не размещая кода в конструкторе.

Пример:

Код


protected:

SOME_STAFF_BEGIN

 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)

SOME_STAFF_END

TClass1(){};
~TClass1(){};



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

Код

#define BEGIN_MESSAGE_MAP                           \

    virtual void __fastcall Dispatch(void *Message) \

    {                                               \

            switch  (((PMessage)Message)->Msg)      \

            {

#define VCL_MESSAGE_HANDLER(msg,type,meth)          \

                case    msg:                        \

                    meth(*((type *)Message));       \

                    break;

#define END_MESSAGE_MAP(base)                       \

                default:                            \

                    base::Dispatch(Message);        \

                    break;                          \

            }                                       \

    }



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

Как бы избавится от дополнительной писанины в конструкторе. Чтобы на этапе описания полей класса уже были созданы все условия для вызова метода.

Рассмотрю любые идее и хаки в том числе, в силу того что моя надстройка собственно и есть грязный хак.



2vinter
Цитата

Цитата(vaddsm @  6.9.2008,  04:10 )
чтобы конструктор класса TClass1 не был задействован


Цитата(vaddsm @  6.9.2008,  04:10 )
при инициализации экземпляра класса TClass1 выполнился код (функция) с параметром


не замечаешь противоречий?



А какие здесь противоречия? В первом представленном примере, как раз так и происходит, проблем только в том, что без параметра. Конструктор TClass1 явным образом не задействован а сообщение появляется (MessageBox).



Это сообщение отредактировал(а) vaddsm - 6.9.2008, 14:27
PM MAIL   Вверх
Alek86
Дата 6.9.2008, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

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



Цитата(vaddsm @  6.9.2008,  14:16 Найти цитируемый пост)
Как бы избавится от дополнительной писанины в конструкторе. Чтобы на этапе описания полей класса уже были созданы все условия для вызова метода.

для этого у классов должен быть предок, конструктор которого и делает, что тебе надо (в данном случае вызывает Dispatch)

Добавлено через 2 минуты и 46 секунд
если в Dispatch нужен параметр, то у тебя 2 варианта

1. чтобы твой класс передавал что надо в вызове конструктора родителя
2. чтобы конструктор родителя использовал глобальную (можно статическую) переменную, в которую ты заранее должен записать нужное значение.

а чтобы куда-то не знаю куда само передавалось что-то, не знаю что - так не бывает


--------------------
user posted image    user posted image
PM MAIL   Вверх
vaddsm
  Дата 6.9.2008, 15:01 (ссылка)    | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Что ж, проблеск понимания (Alek86) появился, и это замечательно! 

Цитата

для этого у классов должен быть предок, конструктор которого и делает, что тебе надо


Наличие такого исключается, необходима реализация для любого класса.

Цитата

а чтобы куда-то не знаю куда само передавалось что-то, не знаю что - так не бывает


Что, куда, а самое главное для чего я знаю на 100% (а что, я где то дал повод в этом сомневаться?). Я не знаю пока только, как и возможно ли? 


Предлагаю рассмотреть, такой пример: В классе есть метод, необходимо его выполнить сразу после инициализации объекта в памяти, при этом конструктор класса должен оставаться незадействованным в вызове этого метода.

PM MAIL   Вверх
Alek86
Дата 6.9.2008, 15:10 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1299
Регистрация: 30.1.2007
Где: Киев

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



Цитата(vaddsm @  6.9.2008,  15:01 Найти цитируемый пост)
Наличие такого исключается, необходима реализация для любого класса.

не выйдет
я допишу с1.cpp
Код
class C1 {};

и все


а если (чтобы побороть мой пример) хочешь извращаться, и делать подобные "фичи"
Код

#define class ERROR_BAD_CLASS_DEFINITION

# define CLASS_BEGIN /*реализация*/
# define CLASS_END /*реализация*/

то (кроме того, что тебе нужна поддержка прекомпилед хедеров (она не везде есть)) пусть земля тебе будет пухом, ибо никто (включая тебя) потом твою прогу не поймет

и выражения типа
Цитата(vaddsm @  6.9.2008,  15:01 Найти цитируемый пост)
Что ж, проблеск понимания

Цитата(vaddsm @  6.9.2008,  15:01 Найти цитируемый пост)
Что, куда, а самое главное для чего я знаю на 100% (а что, я где то дал повод в этом сомневаться?).

прибереги, пожалуйста, для школьников.
тут большинство людей намного больше тебя в С++ разбираются, и если, по-твоему, они говорят не о том, что тебе надо, то это ТЫ виноват, так как плохо объяснил

иначе тебе просто накидают кучу минусов и, с мотря на твой рейт, никто тебе на форуме и пытаться помочь не будет


--------------------
user posted image    user posted image
PM MAIL   Вверх
vaddsm
  Дата 6.9.2008, 15:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Alek86, прежде всего спасибо за желание помочь. Но как то ты агрессивно настроен, в словах проблеск понимания, имелось ввиду, что ты и есть тот самый проблеск, ведь до тебя в сути вопроса не разобрался никто. Так, что это скорее был комплимент. Затем, я бы не брался утверждать сразу, что знаю язык лучше тебя, так, как не видел твоего кода и с тобой лично не общался. По этому выражение “тут большинство людей намного больше тебя в С++ разбираются”, ты уж прости но звучит не очень зрело. Вопрос действительно на первый взгляд, касается основы основ, но это не говорит о том что его решение примитив.

Давай прекратим словесную перепалку, и вернемся к сути вопроса. Прежде всего, почему ты счел 

Код

class C1 {};


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

Код

SOME_STAFF_BEGIN

 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)

SOME_STAFF_END


Необходимо описать в protected секции класса. Тогда, правильное его применение будет иметь форму:


Код

class C1 
{

protected:

SOME_STAFF_BEGIN

 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)

SOME_STAFF_END


};



Другое дело, понуждать пользователя писать еще код в конструкторе 


Код

C1()
{

SOME_STAFF _INIT

};



Это сообщение отредактировал(а) vaddsm - 6.9.2008, 15:38
PM MAIL   Вверх
vinter
Дата 6.9.2008, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  6.9.2008,  15:16 Найти цитируемый пост)
А какие здесь противоречия? 


Цитата(vaddsm @  6.9.2008,  15:16 Найти цитируемый пост)
конструктор класса TClass1 не был задействован


Цитата(vaddsm @  6.9.2008,  15:16 Найти цитируемый пост)
при инициализации экземпляра класса TClass1

ясно?

Цитата(vaddsm @  6.9.2008,  16:01 Найти цитируемый пост)
Предлагаю рассмотреть, такой пример: В классе есть метод, необходимо его выполнить сразу после инициализации объекта в памяти, при этом конструктор класса должен оставаться незадействованным в вызове этого метода.

В С++ это невозможно.


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
  Дата 6.9.2008, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



2vinter. Эти цитаты я так понял, были взяты из этого предложения:

Цитата

Конструктор класса TClass1 не был задействован, но при инициализации экземпляра класса TClass1 выполнился код



А где в нем собственно противоречие? 


Код

class TClass1
{
 
  TClass2 Class2;

  public:

  TClass1(){};
  ~TClass1(){};
};



Конструктор явно не задействован:
Код


  TClass1(){};



А код всеже выполняется! (MessageBox)


Код

В С++ это невозможно.


Вот и я с такими мыслями пришел на форум, но сколько раз убеждался на практике, что нет ничего невозможного. Может все же можно пойти на хитрость?

PM MAIL   Вверх
Fin
Дата 6.9.2008, 17:07 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дракон->Спать();
**


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

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



Вопрос остается в силе, Для чего данное действо вообше нужно?


--------------------
Пролетал мимо.
PM MAIL   Вверх
vinter
Дата 6.9.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  6.9.2008,  17:57 Найти цитируемый пост)
Конструктор явно не задействован:

но задействован ;)

Цитата(vaddsm @  6.9.2008,  17:57 Найти цитируемый пост)
что нет ничего невозможного

попробуй на досуге задницей через форточку вылезти, стандартную форточку совестких домов

Цитата(vaddsm @  6.9.2008,  17:57 Найти цитируемый пост)
 Может все же можно пойти на хитрость?

при инициализации объекта выполняется только конструктор(конструктор копирования) и больше ничего. Все остальное надо вызывать отдельно, либо из самого конструктора. 
Можно конечно сделать класс обертку, через который будут созадваться все объекты. Так же этот класс будет выполнять некую функциональность при создании. Но это сильно ограничит параметаризаию создаваемых объектов.


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 6.9.2008, 17:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Тут ооочень из далека заходить надо, чтобы полностью вопрос раскрыть. Но можно и в кратце: Есть набор функций, которые реализуют некоторое преобразование полей класса, скажем изменяют поведение некоторых методов этого класса. 

Например, установив служебное слово virtual перед методом void __fastcall Method1();, мы указываем компилятору, что необходимо сделать данную функцию виртуальной и внести ее в VMT, DYNAMIC соответственно в DMT. У меня реализовано некоторое подобие VMT, но методы заносятся туда не на стадии компиляции а уже в рантайме. Собственно, для функций, которые реализуют с методами класса, нужные мне действия я пишу удобный интерфейс.

Чтобы, это было настоль же лаконично и просто, как поставит фразу virtual в начале метода. Не нагружать пользователя сложными конструкциями, которые нужно прописывать в различные области класса (в том числе в конструктор).

Например так как я писал:

Код

class C1 
{

protected:

SOME_STAFF_BEGIN

 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)

SOME_STAFF_END


};


Но, пока не придумал варианта проще чем, еще и в конструктор вносить  
Код

SOME_STAFF_INIT.



P.S Предлагаю пока откинуть универсальные кроссплатформенные методы, если таких нет для решения данной задачи, и сосредоточить внимание на средах BCB и VS. Любые конструктивные идеи приветствуются!



Это сообщение отредактировал(а) vaddsm - 6.9.2008, 18:24
PM MAIL   Вверх
mes
Дата 6.9.2008, 18:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  6.9.2008,  14:16 Найти цитируемый пост)
Ты это к чему сказал то? Разве из моего сообщения следует, что я хочу создать ОБЪЕКТ не задействовав в этом мероприятии его КОНСТРУКТОР. Прошу перед тем, как что либо  писать, внимательно вникать в суть поставленной задачи. 


Цитата(vaddsm @  6.9.2008,  03:10 Найти цитируемый пост)
Мне необходимо добиться того, чтобы конструктор класса TClass1 не был задействован, но при инициализации экземпляра класса TClass1 выполнился код (функция) с параметром.


Не был задействован- означает не вызывается. Так что на ваш ответ могу ответить : прежде, чем спрашивать, сформулируйте нормально вопрос! 



Цитата(vaddsm @  6.9.2008,  14:16 Найти цитируемый пост)
Например в VCL есть подобная реализация, таблица регистрирующая функции-обработчики оконных сообщений. 

Вы наверно будете сильно удивлены, но в приведенном примере ни одна строчка не выполняется при инициализации. В том числе и метод Dispatch (). 

Цитата(vaddsm @  6.9.2008,  16:57 Найти цитируемый пост)
Конструктор явно не задействован:
Код

  TClass1(){};

А код всеже выполняется! (MessageBox)

Потому что задействован!!!  конструктор по умолчанию  smile 

Цитата(vaddsm @  6.9.2008,  16:57 Найти цитируемый пост)
Может все же можно пойти на хитрость?

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


Цитата(Fin @  6.9.2008,  17:07 Найти цитируемый пост)
Вопрос остается в силе, Для чего данное действо вообше нужно? 


Цитата(vaddsm @  6.9.2008,  17:32 Найти цитируемый пост)

Есть набор функций, которые реализуют некоторое преобразование полей класса, скажем изменяют поведение некоторых методов этого класса...
Чтобы, это было настоль же лаконично и просто, как поставит фразу virtual в начале метода. Не нагружать пользователя сложными конструкциями, которые нужно прописывать в различные области класса (в том числе в конструктор).


Что скрыто тут ? :
Цитата(vaddsm @  6.9.2008,  17:32 Найти цитируемый пост)
SOME_STAFF_BEGIN
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
SOME_STAFF_END


Цитата(vaddsm)

Предлагаю рассмотреть, такой пример: В классе есть метод, необходимо его выполнить сразу после инициализации объекта в памяти, при этом конструктор класса должен оставаться незадействованным в вызове этого метода.
...
Но, пока не придумал варианта проще чем, еще и в конструктор вносить  

Код

SOME_STAFF_INIT.



Ну a если добавить в Ваш дефайн  строчку добавляюшая в нужный класс  регистратор(или другой вспомогательный объект) с конструктором по умолчанию ?

Это сообщение отредактировал(а) mes - 6.9.2008, 18:44


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 6.9.2008, 18:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



mes

Цитата

Цитата(vaddsm @  6.9.2008,  14:16 Найти цитируемый пост)
Например в VCL есть подобная реализация, таблица регистрирующая функции-обработчики оконных сообщений. 

Вы наверно будете сильно удивлены, но в приведенном примере ни одна строчка не выполняется при инициализации. В том числе и метод Dispatch ().



Вы наверно, будете еще больше удивлены обнаружив, в том посте, откуда вы взяли эти строчки, следующие слова:

Проблема, в том что, метод Dispatch применяется в самом классе в нужном месте и в нужное время. В моем случае я делаю произвольную надстройку на любой класс и он, о моем подобии Dispatch ни сном не духом, по этому приходится прописывать вызов этого метода еще и в конструкторе…
 
Мне даже обидно как-то, ведь я сам написал об этом подробно.

 
Цитата

Цитата(vaddsm @  6.9.2008,  16:57 Найти цитируемый пост)
Конструктор явно не задействован:
Код

  TClass1(){};

А код всеже выполняется! (MessageBox)

Потому что задействован!!!  конструктор по умолчанию  smile



Ок, здесь действительно мои слова можно было понять не правильно. Сказав “Конструктор явно не задействован” я имел ввиду, что мы руками не прописываем сюда TClass1(){/*Ничего*/};. Хотя, компилятор, еще да точки /*Ничего*/ помещает инструкции вызывающие конструктор TClass2. А в котором, уже в свою очередь, следует код вызывающий MessageBox.

PM MAIL   Вверх
mes
Дата 6.9.2008, 18:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  6.9.2008,  18:47 Найти цитируемый пост)
Мне даже обидно как-то, ведь я сам написал об этом подробно.


Цитата(vaddsm @  6.9.2008,  18:47 Найти цитируемый пост)
 В моем случае я делаю произвольную надстройку на любой класс и он, о моем подобии Dispatch ни сном не духом, по этому приходится прописывать вызов этого метода еще и в конструкторе…

Я расценил эти слова, что в Вашем коде надо прописывать вручную, а в VCL это делается автоматом. Но в примере не нашел ничего подобного. smile 
тем более что перед примером шла строчка :
Цитата(vaddsm @  6.9.2008,  14:16 Найти цитируемый пост)

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

тут по контексту возникает смысл, что регистрация происходит в момент инициализации..

Если Вы имели ввиду виртуальность Dispatch,  (инициализацию указателя на VMT) то причем тут вобще VCL ?



Это сообщение отредактировал(а) mes - 6.9.2008, 18:57


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 6.9.2008, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



mes, все похоже, что Вы меня поняли. Искренне спаибо! 


Цитата

Ну a если добавить в Ваш дефайн  строчку добавляюшая в нужный класс  регистратор(или другой вспомогательный объект) с конструктором по умолчанию ?


У меня так:
Код


#define MSL_TABLE_BEGIN TMethodSpliceInterface MSL;                                         \
void __fastcall MSL_INIT()                                                                  \
{
#define REPLACE_INCURINST_METHOD(lpOriginlMethod, CallType, lpDstMethod, lpInheritedMethod) \
MSL.ReplaceMethod(CallType, SPLICE_CURRENT_INST,                                  \
&lpOriginlMethod, &lpDstMethod, &lpInheritedMethod);
#define REPLACE_INALLINST_METHOD(lpOriginlMethod, CallType, lpDstMethod, lpInheritedMethod) \
MSL.ReplaceMethod(CallType, SPLICE_ALL,                                           \
&lpOriginlMethod, &lpDstMethod, &lpInheritedMethod);
#define MSL_TABLE_END                                                                       \
}

#define MSL_TABLE_INIT MSL_INIT();



Проблема MSL_TABLE_INIT, приходится в конструктор класса помещать.

P.S. Если после этого поста остаются еще вопросы, прошу задовать.


Это сообщение отредактировал(а) vaddsm - 6.9.2008, 19:46
PM MAIL   Вверх
mes
Дата 6.9.2008, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Вам необходим this для вашей таблицы либо косвенно (как у вас в примере), либо прямо.
"Автоматически"при инициализации его можно получить только в конструкторе, того объекта,
методы которого вам нужно делегировать.
ИМХО, решить задачу, не затрагивая конструктора, нереально. 


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


Шустрый
*


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

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



Цитата

P.S Предлагаю пока откинуть универсальные кроссплатформенные методы, если таких нет для решения данной задачи, и сосредоточить внимание на средах BCB и VS. Любые конструктивные идеи приветствуются!


 smile Ну так, что в средах BCB и VS, подобное не реализуемо? smile Прошу поднять правую руку, всех кто уверен что это так ).
PM MAIL   Вверх
mes
Дата 6.9.2008, 22:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Мне кажется Вы не туда акцент поставили в вопросе.
В данном исполнении у Вас, основная загвоздка на мой взгляд не в использовании конструктора,
а в том , что пользователь может забыть добавить нужную строчку, для инициализации.
Чтоб избежать подобного, надо научить компилятор сообщать об этом.
Поэтому предлагаю реализовать описание таблицы внутри вспомогательного класса, для инициалиции которого требуется this основного.
Тогда даже если пользователь добавит несколько конструкторов к основному классу, то компилятор не позволит не проинициализировать таблицу.  smile 


--------------------
PM MAIL WWW   Вверх
vaddsm
  Дата 6.9.2008, 23:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

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


Абсолютно, точно. Можно, конечно и ваш вариант, если я его правильно понял.

Давайте на практике рассмотрим (простенький пример), того, что именно Вы имеете ввиду.

Предположим дан вспомогательный класс Tmsl, у него есть метод void __fastcall dosomestuff(LPVOID PointerTo_PrimaryClass_Member); Вызывая данный метод я произвожу действия над членами основного класса. И допустим, есть основной класс, назовем его TPrimaryClass. Из данных условий, как ваша идея должна быть выражена в коде?



PM MAIL   Вверх
Lazin
Дата 6.9.2008, 23:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



тем кто понял суть вопроса, расскажите в 2х словах...

Цитата(vaddsm @  6.9.2008,  15:01 Найти цитируемый пост)
Предлагаю рассмотреть, такой пример: В классе есть метод, необходимо его выполнить сразу после инициализации объекта в памяти, при этом конструктор класса должен оставаться незадействованным в вызове этого метода.

вопрос поставлен не точно, что за метод, виртуальный, закрытый, статический...

сразу напрашиваются два решения:
  • фабрика объектов (можно сделать так, что-бы экземпляр класса можно было создать только с помощью фабрики)
  • умный указатель (можно сделать так, что-бы с объектом можно было работать только через определенный smart-pointer)



Цитата(vaddsm @  6.9.2008,  15:36 Найти цитируемый пост)
class C1 
{
protected:
SOME_STAFF_BEGIN
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
 DO_SOME_WORK(…)
SOME_STAFF_END
};

там где я работаю, за такой код могут и уволить... smile 

Это сообщение отредактировал(а) Lazin - 6.9.2008, 23:11
PM MAIL Skype GTalk   Вверх
mes
Дата 6.9.2008, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  6.9.2008,  23:09 Найти цитируемый пост)
тем кто понял суть вопроса, расскажите в 2х словах...

задача:  делегировать произвольные методы одного объекта объекту обработчику.
Само делегирование проблем не вызывает. Вопрос как красиво оформить, чтоб клиент, мог интуитивно использовать
библиотеку, и компилятор предупредил бы в случае ошибки/упущения.

Добавлено @ 23:36
Цитата(vaddsm @  6.9.2008,  23:02 Найти цитируемый пост)
Предположим дан вспомогательный класс Tmsl, у него есть метод void __fastcall dosomestuff(LPVOID PointerTo_PrimaryClass_Member); Вызывая данный метод я произвожу действия над членами основного класса. И допустим, есть основной класс, назовем его TPrimaryClass. Из данных условий, как ваша идея должна быть выражена в коде?


Не до конца понял, что имели тут ввиду.
Как насчет такого? использование виртуальности для реализации callback'a
Код


class Imsl
{
  public:
     void SomeStuff () {doSomeStuff (); }
  protected:     
      virtual void doSomeStuff ()   =0;
};

class Class1
{
      Tmsl : public Imsl
     {
        public:
          Tmsl (Class1 *p) : p_obj (p) {}
        protected:     
              void doSomeStuff ()  { p_obj ->doSomeStuff(); }
        private:
          Class1 *p_obj;
     } m_msl;

    public:
 
        Class1 () : m_msl(this) {} 
 
  protected:     
        void doSomeStuff ()  {... }
   
};

 


Это сообщение отредактировал(а) mes - 6.9.2008, 23:37


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 6.9.2008, 23:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

там где я работаю, за такой код могут и уволить...


Возможно, оффтоп и все же, что не так в примере то? (в двух словах)

Цитата

вопрос поставлен не точно, что за метод, виртуальный, закрытый, статический...


Есть класс, совершенно любой, со своим набором методов и свойств. И у нас есть универсальный инструмент (другой класс), совершающий действия над методами любого класса. Для этого инструмента надо написать удобный интерфейс. 

Пример, есть класс над которым совершается действо:


Код

Class ExampleCalss
{

  protected:

   int any_var1;
   int any_var2;
   int any_var3;

  public:

  void __fastcall Method1();
  void __fastcall Method2();
  void __fastcall Method3();

  __fastcall ExampleCalss();
  __fastcall ~ExampleCalss();

};


Применительно к нему, код выполняющий интерфейс для “Инструмента”, выглядит так:


Код

Class ExampleCalss
{

  protected:

   int any_var1;
   int any_var2;
   int any_var3;

  public:

  void __fastcall Method1();
  void __fastcall Method2();
  void __fastcall Method3();

  TOOL_TABLE_BEGIN
  
  DO_ACTION(Method1, Method2)
  DO_ACTION(Method3, Method2)
  TOOL_TABLE_END


  __fastcall ExampleCalss();
  __fastcall ~ExampleCalss();

};



Все замечательно, красиво, удобно, но приходится писать еще в конструктор:


Код

__fastcall ExampleCalss::ExampleCalss()
{
 TOOL_TABLE_INIT
};


А ооочень не хотелось бы.

Пример дефайнов для TOOL_TABLE я выложил выше.

Добавлено @ 23:46
Цитата

задача:  делегировать произвольные методы одного объекта объекту обработчику.
Само делегирование проблем не вызывает. 



Ну, ну нет не такая задача.

Цитата

Вопрос как красиво оформить, чтоб клиент, мог интуитивно использовать
библиотеку, и компилятор предупредил бы в случае ошибки/упущения.


Вопрос, верный!


Это сообщение отредактировал(а) vaddsm - 6.9.2008, 23:49
PM MAIL   Вверх
Lazin
Дата 6.9.2008, 23:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



ради бога
Код

template<class Derived>
class MyClass : public Derivde
{
public:
    MyClass()
    {
        //вызывается после создания Derived
        std::cout << "initialization done" << std::endl;
    }
    void some_method(int param)
    {    
        some_method_impl(param); 
    }
};

class impl_
{
    void some_method_impl(int param)
    {
        std::cout << "Implementation" << std::endl;
    }
};


typedef MyClass<impl_> MyImpl;

MyImpl instanse;
instanse.some_method(111);

вот вам и вызов сразу после инициализации)) 

Это сообщение отредактировал(а) Lazin - 7.9.2008, 00:09
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 6.9.2008, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Хотел вам mes + поставить за огромное стремление помочь, но не дают пока это сделать, говорят постов мало. 

mes, пока не то. По последнему посту есть вопросы?


PM MAIL   Вверх
mes
Дата 6.9.2008, 23:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  6.9.2008,  23:39 Найти цитируемый пост)
  TOOL_TABLE_BEGIN
  
  DO_ACTION(Method1, Method2,)
  DO_ACTION(Method3, Method2,)
  TOOL_TABLE_END



Код

class IAction
{
  public:
  virtual void  Method1() {}
  virtual void  Method2() {}
  virtual void  Method3() {}
  virtual  IAction() {}
}

#define TOOL_TABLE_BEGIN(Class) class CAction : public IAction { Class p_obj; public: CAction(Class *p) : p_obj (p) {};                                                                            
#define DO_ACTION(Method1, Method2) void Method1() { p_obj->Method2(); }
#define TOOL_TABLE_END } m_Action;
#define INIT_TABLE m_Action(this)
#define INIT_TABLE_(Class) Class() :m_Action(this) {}


Код

Class ExampleCalss
{
  protected:
   int any_var1;
   int any_var2;
   int any_var3;
  public:
  void Method1();
  void Method2();
  void Method3();
  TOOL_TABLE_BEGIN(ExampleCalss)
  
  DO_ACTION(Method1, Method2)
  DO_ACTION(Method3, Method2)
  TOOL_TABLE_END
  ExampleCalss(int a): INIT_TABLE {} // инициализация внутри конструктора

  INIT_TABLE_(ExampleCalss)  //инициализация с добавлением конструктора по умолчанию.

   ~ExampleCalss();
};



Это сообщение отредактировал(а) mes - 7.9.2008, 00:01


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Lazin, не то, не правильно Вам прояснил суть mes. Прочитайте мой последний пост, может, станет яснее. Дело в том что мой “инструмент” пользователь будет применять к своему MyClass, а как он у него объявлен, от какого класса унаследован, это сугубо его дело и я не хочу его как либо в этом ограничивать.
PM MAIL   Вверх
mes
Дата 7.9.2008, 00:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



в Борланде Вы можете кстати описать указатель на метод  с помощью __closure и на этом построить таблицу 

Это сообщение отредактировал(а) mes - 7.9.2008, 00:12


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 00:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ван, момент, дайте дочитаю mes'a , пока не псте сообщений!
PM MAIL   Вверх
mes
Дата 7.9.2008, 00:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  00:00 Найти цитируемый пост)
Дело в том что мой “инструмент” пользователь будет применять к своему MyClass, а как он у него объявлен, от какого класса унаследован, это сугубо его дело и я не хочу его как либо в этом ограничивать

То есть Вы хотите чтоб любой пользовательский класс мог легко использовать свое тело для Библиотечного интерфейса.
Процесс передачи реализации интерфейсу называется делегацией. 
Вы хотите своими макросами(или другими способами) упростить делегацию. Правильно ?
помимо прямой делегации упомянутой в предыдущих примерах можно например использовать борландскую __closure, бустовые сигналы,
библиотеку FastDelegate (http://www.rsdn.ru/article/cpp/fastdelegate.xml) , или Winnie.Closure (http://dobrokot.nm.ru/cpp/CppMethodsCallback.html)




--------------------
PM MAIL WWW   Вверх
Lazin
Дата 7.9.2008, 00:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vaddsm @  7.9.2008,  00:00 Найти цитируемый пост)
Прочитайте мой последний пост, может, станет яснее. Дело в том что мой “инструмент” пользователь будет применять к своему MyClass, а как он у него объявлен, от какого класса унаследован, это сугубо его дело и я не хочу его как либо в этом ограничивать. 

хозяин - барин, я вам расхожую идиому привел, которая как раз и предназначена для диспетчеризации вызовов методов

Добавлено через 12 секунд
объекта
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 7.9.2008, 00:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

То есть Вы хотите чтоб любой пользовательский класс мог легко использовать свое тело для Библиотечного интерфейса.


Да.

Цитата

Вы хотите своими макросами(или другими способами) упростить делегацию. Правильно ?


Нет, речь не идет о делегации, вовсе. Там совершенно другие задачи. Мой макрос:

Код

#define REPLACE_INALLINST_METHOD(lpOriginlMethod, CallType, lpDstMethod, lpInheritedMethod) \
MSL.ReplaceMethod(CallType, SPLICE_ALL,                                           \
&lpOriginlMethod, &lpDstMethod, &lpInheritedMethod);


Работает с адресами любых методов. Да и причем здесь методы, буть тут хоть переменные, члены класса, не важно! 
MSL.ReplaceMethod может оставаться черным ящиком, в рамках, задачи. 

Предложеный вами метод, всеьма изящен, хоть и не помогает решить задачу о которой я говорю. Опять ведь приходиться таскать за собой  ExampleCalss(int a): INIT_TABLE {} или  INIT_TABLE_(ExampleCalss). Было бы класно, если после слова TOOL_TABLE_END, пользователь мог забыть, о том, что от него что-то требуется еще.

PM MAIL   Вверх
mes
Дата 7.9.2008, 00:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  00:33 Найти цитируемый пост)
пять ведь приходиться таскать за собой  ExampleCalss(int a): INIT_TABLE {} или  INIT_TABLE_(ExampleCalss). 

ага, я  уже писал smile
Цитата(mes @  6.9.2008,  19:51 Найти цитируемый пост)
ИМХО, решить задачу, не затрагивая конструктора, нереально. 

Я лишь привел пример организации таблицы, который не компилится если забыли проинициализоровать.

Добавлено @ 00:50
Цитата(vaddsm @  7.9.2008,  00:33 Найти цитируемый пост)
Работает с адресами любых методов. 

так механизм можете оставить свой спрятав весь механизм внутри вспомогательного класса по аналогии приведенных выше примеров или   добавив dummy - инициализатор

#define INITIATOR(Class) class Initiator { public: Initiator (Class *p) { p->Init(); } } m_Initiator;
если этот макрос спрятать в макросах описания таблицы, то пользователь не сможет забыть проинициализировать вашу таблицу



Это сообщение отредактировал(а) mes - 7.9.2008, 01:00


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 01:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Mes, да все верно, Ваш пример отлично решит задачу о целостности конструкции, назавем ее так. Еще раз отмечу, что мне ооочень понравилось. Но я пока еще хочу поломать голову над тем, чтобы эту самую конструкцию окончить на слове TOOL_TABLE_END. Спасибо, за помощь! Плюс пока не могу поставить (постов мало).  

Если у кого будут идеи в сторону "непрописывания" кода в конструктор, я буду рад!
PM MAIL   Вверх
mes
Дата 7.9.2008, 01:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



а как библиотека использует TMethodSpliceInterface ?
Он автоматически регистрируется при создании, или это делается внешней функцией?


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 02:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Код

#define MSL_TABLE_BEGIN TMethodSpliceInterface MSL;    


Экземпляр такого объекта создается при инициализации в памяти экземпляра класса над которым мы собираемся производить действия. 

Это сообщение отредактировал(а) vaddsm - 7.9.2008, 02:13
PM MAIL   Вверх
mes
Дата 7.9.2008, 02:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  02:11 Найти цитируемый пост)
Экземпляр такого объекта создается при инициализации в памяти экземпляра класса над которым мы собираемся производить действия. 

то что создается объект MSL, я видел. Как библиотека управляет этим интерфейсом ?
просто запрашивается этот интерфейс у хозяина или он должен быть где то зарегестрирован?


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 02:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Пускай вас не смущает присутствие в название слова Interface, на самом деле это не абстрактный класс. Это обычный класс содержащий несколько методов, в задачу которого входит принять передоваемые параметры, обработать их и передать в нужном формате на вход внешней функции описаной в lib. Вообщем класс это "обычный", нет нигде он не регистрируется.

Это сообщение отредактировал(а) vaddsm - 7.9.2008, 02:38
PM MAIL   Вверх
mes
Дата 7.9.2008, 02:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  02:37 Найти цитируемый пост)
Пускай вас не смущает присутствие в название слова Interface, на самом деле это не абстрактный класс. Это обычный класс содержащий несколько методов, в задачу которого входит принять передоваемые параметры, обработать их и передать в нужном формате на вход внешней функции описаной в lib. Вообщем класс это обычный, нет нигде он не регистрируется. 


Нисколько не пугает название этого слова. Вопрос как происходит вызов нужного метода этого класса ?
ну, например, есть такое:
Код

class Class1 { private: TMethodSpliceInterface MSL;  ... } myObj;

кто, когда и как получает указатель на MSL ?

Это сообщение отредактировал(а) mes - 7.9.2008, 02:56


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 02:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Я же написал TMethodSpliceInterface - не абстрактный класс. А вызов его методов осуществляется:

Код

class TClass1
{

 public:

 TMethodSpliceInterface MSL;

 void CallFuntion()
 {

  MSL.Method1(...);
  MSL.Method2(...);
  MSL.Method3(...);
  MSL.Method4(...);

 }

 TClass1()
 {
  CallFuntion();
 }

}


И только. На этом область применения его оканчивается.
PM MAIL   Вверх
mes
Дата 7.9.2008, 03:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



[color=silver]
Цитата(vaddsm @  7.9.2008,  02:50 Найти цитируемый пост)
Я же написал .. не абстрактный класс

сорри - ночь на дворе )
Цитата(vaddsm @  7.9.2008,  02:50 Найти цитируемый пост)
А вызов его методов осуществляется:

Ну а с примером Вы перемудрили 

Правильно ли я понял:
1. Посредством интерфейса MSL , мы можем управлять состоянием хозяина
2. MSL - предоставляет некий общий интерфейс 
3. Вызов методов MSL происходят на стороне клиeнта удобным ему способом.

Добавлено через 4 минуты и 57 секунд
Цитата(mes @  7.9.2008,  03:03 Найти цитируемый пост)
не абстрактный 

это принципиальная деталь, или просто вариант реализации?


--------------------
PM MAIL WWW   Вверх
vaddsm
  Дата 7.9.2008, 06:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Сделал именно так, как хотел видеть. В BCB работает, сейчас еще в VS отладить осталось.

Код



class TMyLib
{

 public:

 void __fastcall DoSomeStuff(char *Ptr);

 TMyLib(DWORD dwCallAddr);
 ~TMyLib();

};

void __fastcall TMyLib::DoSomeStuff(char *Ptr)
{
 wsprintf(Ptr, "Action fired~!");
};


TMyLib::TMyLib(DWORD lpfn)
{

   :wizard 

};

TMyLib::~TMyLib()
{

};

#define TOOL_TABLE_BEGIN(ClassName)                            \
                                                               \
 class TMyLibInterface                                         \
 {                                                             \
  public:                                                      \
   typedef void __fastcall (ClassName::*lpCallMethod)();       \
   TMyLib *Lib;                                                \
   TMyLibInterface()                                           \
   {                                                           \
    lpCallMethod lpfun = ClassName::CallMethod;                \
    TMyLib *Lib = new TMyLib(*(DWORD *)&lpfun);                \
   };                                                          \
   ~TMyLibInterface()                                          \
   {                                                           \
    delete Lib;                                                \
   }                                                           \
 } MyLibInterface;                                             \
                                                               \
 public:                                                       \
                                                               \
 void __fastcall CallMethod()                                  \
 {                                                             
#define DO_ACTION(WITH) MyLibInterface.Lib->DoSomeStuff(WITH);
#define TOOL_TABLE_END                                         \
 };                                                            \
                                                               \
 protected:


class TAnyClass 
{


 protected:

 char message[50];

 TOOL_TABLE_BEGIN(TAnyClass)
 DO_ACTION(message)
 TOOL_TABLE_END

 public:

 __fastcall  ()
 {
  MessageBox(0, message, "Trick! ;)))", 0);
 };

 __fastcall ~TAnyClass (){};

};




После такой вот строчки:  TAnyClass *Inst = new TAnyClass();

Появляется MessageBox(0,"Action fired~!","Trick! ;)))",0);

Решил интригу сделать  smile . Интересно что в конструкторе TMyLib?




PM MAIL   Вверх
mes
Дата 7.9.2008, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
 __fastcall  ()

борланд позволяет так писать?  smile

Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
Интересно что в конструкторе TMyLib

 smile 
)))

Это сообщение отредактировал(а) mes - 7.9.2008, 13:13


--------------------
PM MAIL WWW   Вверх
mes
Дата 7.9.2008, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



У меня нет вариантов как Вы добыли this  от Inst по смещению метода  (

Добавлено через 4 минуты и 4 секунды
Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
   lpCallMethod lpfun = ClassName::CallMethod;  

тут borland позволяет забыть   "&" ?

Это сообщение отредактировал(а) mes - 7.9.2008, 13:15


--------------------
PM MAIL WWW   Вверх
vinter
Дата 7.9.2008, 13:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(mes @  7.9.2008,  14:12 Найти цитируемый пост)
тут borland позволяет забыть   "&" ?

а почему нет? с & и без него  записи эквивалентны


--------------------
Мой блог
PM MAIL WWW   Вверх
Lazin
Дата 7.9.2008, 13:32 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



не хотел-бы я этот код разбирать smile

Добавлено через 4 минуты и 43 секунды
Цитата(mes @  7.9.2008,  13:12 Найти цитируемый пост)
lpCallMethod lpfun = ClassName::CallMethod;

вообще это не правильно, нужно писать &ClassName::CallMethod но borland позволяет и так...

Добавлено через 7 минут и 27 секунд
Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
TMyLib::TMyLib(DWORD lpfn)

вот то-же ошибка, указатель на функцию не обязан помещаться в DWORD

Добавлено через 9 минут и 53 секунды
в общем код в топку, то-же самое можно сделать красиво с помощью шаблонов...
кстати интересно, что ты будешь делать, когда отладчик тебе покажет на ошибку в строке 
Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
TOOL_TABLE_BEGIN(TAnyClass)

 smile

Добавлено через 12 минут и 1 секунду
неужели этот код собрался без единого предупреждения.... если да, то фтопку борланд smile 
PM MAIL Skype GTalk   Вверх
vinter
Дата 7.9.2008, 13:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(Lazin @  7.9.2008,  14:32 Найти цитируемый пост)
вообще это не правильно, нужно писать &ClassName::CallMethod 

это почему это?


--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 7.9.2008, 14:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Я так до сих пор и не понял кто и как будет использовать интерфейс,
вот еще один основанный на догадках пример, без затрагивания конструктора. 
Таблица составляется на этапе компиляции. В момент создания объекта, никаких(за исключением предусмотренных компилятором, таких как смена указателя на VMT) действий производится не будет.
Связывание интерфейса с реализацией происходит в момент запроса интерфейса.
Никаких лишних переменных в класс хозяин не добавляется . (т.е реально использовать такой вид связывания для чистых абстракных класов)
Естественно , что для удобного использования , можно скрыть все под макросами, как в вышеприведенных примерах. 

Код


class IAnyInterface
{
    public:
       virtual void Method1 () =0;
       virtual void Method2 () =0;
};
class CAnyClass
{

   protected:

    class MyInterface : IAnyInterface 
    {
      public:
           MyInterface (CAnyClass *p) : p_obj(p) {}
                  virtual void Method1 () {p_obj ->Prepare(); p_obj ->Method1(); }
                  virtual void Method2 () {p_obj ->Prepare(); p_obj ->Method2(); }

       private:        
           CAnyClass *p_obj;
    };

      public:
             void CallMethod1 () { MyInterface iface = GetMyInterface(); iface.Method1(); } 
             void CallMethod2 () { GetMyInterface().Method2(); } /

     protected:
        void Method1 () {..}
        void Method2 () {..}
        void Prepare  () {..}

         MyInterface GetMyInterface () { return this; }

};


Это сообщение отредактировал(а) mes - 7.9.2008, 14:39


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 7.9.2008, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vinter @  7.9.2008,  13:54 Найти цитируемый пост)
это почему это?

потому-что мы получаем указатель на функцию smile 

vs2005, позволяет делать только так
PM MAIL Skype GTalk   Вверх
vinter
Дата 7.9.2008, 14:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Lazin, если есть под рукой Страуструп специальное издание. Открой страницу 199.

Цитата(Lazin @  7.9.2008,  15:23 Найти цитируемый пост)
vs2005, позволяет делать только так

макросам ON_WM_SOMETHING можно скормить как func так и &func, разницы не будет. Следовательно VS по баробану, ка ки должно быть.

Добавлено через 29 секунд
2005 не помню, но в 2003 и 2008 точно можно.


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 15:51 (ссылка)    | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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




Цитата

Добавлено через 7 минут и 27 секундЦитата(vaddsm @  7.9.2008,  06:27 )
TMyLib::TMyLib(DWORD lpfn)


вот то-же ошибка, указатель на функцию не обязан помещаться в DWORD



 smile  smile   smile 


Указатель на метод класса НИКОГДА не DWORD, если только он не static __stdcall 
А вот первые 4 байта, всегда адрес метода в памяти, затем, например this... 
Это уже зависит от того, какой это метод, но в данном случае, мы конкретно указали 
void __fastcall.

Цитата

кстати интересно, что ты будешь делать, когда отладчик тебе покажет на ошибку в строке 


С чего ради?

Цитата

в общем код в топку, 



Lazin, а ведь на прошлый пафос, вроде: За такой код меня бы уволили. Ты мне так и не ответил, почему? А сейчас опять необоснованно разбрасываешься словами, и уж тем более:

Цитата

то-же самое можно сделать красиво с помощью шаблонов...


Ну так давай! Докажи что это не болтовня! 

Тайна конструктора TMyLib:

Код


 asm
 {
  push eax
  mov  eax, [ebp]
  mov  eax, [eax]
  mov  eax, [eax-0x04]
  call lpfn
  pop eax

 }


PM MAIL   Вверх
mes
Дата 7.9.2008, 16:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)
Тайна конструктора TMyLib:

А нельзя ли расшифровать, что происходит в ассемблерной вставке ? 





--------------------
PM MAIL WWW   Вверх
Lazin
Дата 7.9.2008, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)
Указатель на метод класса НИКОГДА не DWORD, если только он не static __stdcall 
А вот первые 4 байта, всегда адрес метода в памяти, затем, например this... 
Это уже зависит от того, какой это метод, но в данном случае, мы конкретно указали 
void __fastcall.

ты что-то путаешь
в коде который ты привел
Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
Код

 typedef void __fastcall (ClassName::*lpCallMethod)();


Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
   
Код

 lpCallMethod lpfun = ClassName::CallMethod;                \
    TMyLib *Lib = new TMyLib(*(DWORD *)&lpfun)
; 


ты используешь указатель на метод класса, при чем там this я не в курсе, но я точно знаю что любой указатель нельзя приводить к DWORD, так как указатель может быть и 8-ми байтовым (на 64х битных системах), а указатель на метод или функцию нельзя приводить даже к void*

Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)

С чего ради?

попробуй собрать и запустить свой код под em64t, узнаешь smile 

Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)
Ты мне так и не ответил, почему?

потому-что лень, потому-что выходные smile 

Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)
Тайна конструктора TMyLib:

Цитата(vaddsm @  7.9.2008,  15:51 Найти цитируемый пост)

Код

 asm
 {
  push eax
  mov  eax, [ebp]
  mov  eax, [eax]
  mov  eax, [eax-0x04]
  call lpfn
  pop eax
 }

по твоему это входит в противоречие с тем что я говорил? Здесь происходит вызов функции, но, где гарантия что lpfn нужно вызывать именно так, ведь в своем коде ты делаешь С-style cast и приводишь указатель на функцию к DWORD, и в принципе, туда можно передать любую функцию... 
в общем так не делают

Добавлено через 2 минуты и 3 секунды
просвети, что это 
Цитата(vaddsm @  7.9.2008,  06:27 Найти цитируемый пост)
__fastcall  ()
 такое?

PM MAIL Skype GTalk   Вверх
vaddsm
  Дата 7.9.2008, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Да канеш можно. 

Прежде всего давайте рассмотри начало любой функции описанной средствами языка c++ в машинном коде:

Код

00426100 55                push ebp
00426101 8BEC            mov ebp,esp


Как известно, регистр ESP – это указатель на текущий адрес в стеке, тогда из приведенного примера однозначно следует, что начало каждой функции ознаменуется:


1.    Сохранением в стек регистра EBP, содержащего адрес начала стека вызывающей функции.
2.    Записью в регистр EBP, текущего адреса в стеке.

Благодаря этому правилу мы всегда можем раскрутить стек и дойти до начала стека интересующей нас функции. В нашем случае крутить ) придется не долго. Но так, как для выполнения этой операции нам потребуется один регистр, необходимо позаботится о том, чтобы его первоначальное значение не было утеряно:

Код

push eax


Далее, получим адрес начала стека конструктора класса TMyLib.

Код

mov  eax, [ebp]


Так, как конструктор класса TMyLib  вызывается из конструктора шаблонного класса TMyLibInterface, получим начало стека и этого конструктора.

Код

mov  eax, [eax]


Мы уже у цели, финишная прямая – получение адреса начала стека конструктора класса над которым производим действие, в данном случае, это TAnyClass.

Код

mov  eax, [eax-0x04]


Но в данном случае мы берем значение не из ячейки стека, в которой находится очередной EBP, а на 4 байта выше, именно туда функция – метод класса помещает указатель. А как по вашему работает отладчик, который всегда в Watches, вам покажет значения локальных переменных. Вот, например как сохраняет this, fastcall метод:

Код

00426107 8945FC           mov [ebp-0x04], eax


После приведенных инструкций, в EAX у нас содержится адрес экземпляра TAnyClass. Почему именно EAX, спросите вы, а все очень просто, функции скомпилированных по конвенции fastcall принимают указатель this именно в этом регистре. Адрес метода, который мы будем вызывать у нас уже есть, это lpfn. Не будет терять время даром, nop, nop, nop )). Вызываем:

Код

call lpfn


Вот и все, теперь для чистоты эксперимента, вернем все туда, где оно и лежало.

Код

pop eax














Это сообщение отредактировал(а) vaddsm - 7.9.2008, 17:20
PM MAIL   Вверх
vinter
Дата 7.9.2008, 17:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  7.9.2008,  16:51 Найти цитируемый пост)
а ведь на прошлый пафос, вроде: За такой код меня бы уволили. Ты мне так и не ответил, почему? 

я отвечу.
1. Куча макросов, код тяжело читать.
2. Код -  костыль, не то что палтформо - а компиляторо зависим.
3. Мне сходу не понятно, что делает втой код, и не факт что я бы быстро вьехал, если бы не знал. Это показатель, для меня.


Это сообщение отредактировал(а) vinter - 7.9.2008, 17:27


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 17:37 (ссылка)    | (голосов:3) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

ты используешь указатель на метод класса, при чем там this я не в курсе


БОГ МОЙ! Гуру c++! Как по вашему указатель на метод класса соотносится с экземпляром класса, такой указатель как минимум должен содержать this и адрес самого метода в памяти. 

Цитата

ты что-то путаешь
в коде который ты привел


Еще раз, указатель на метод класса, как минимум 8 байт, он может быть и 12 и 16 байт. Одно остается неизменным, то, что, такая вот конструкция  *(DWORD *)&lpfun, вернет нам только, 4 байта - адрес самого метода, в случае если метод объявлен void, vod __fastcall, void __stdcall и тд и тп. 

С 64x разрядными системами я не работал, по этому демогогии не будет, хотя и для этого случая можно предусмотреть отдельный дефайн.

Цитата

попробуй собрать и запустить свой код под em64t


Так надо, говорю же, дефайн в крайнем случае добавить один, а так в принципе, можно и в этой форме попробывать.

 
PM MAIL   Вверх
Lazin
Дата 7.9.2008, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Код

template < 
    class UserClass, 
    void (UserClass::*Delegate)() = &UserClass::operator()
>
class tool_table_wrapper : public UserClass
{
public:
    tool_table_wrapper()
    {
        (static_cast<UserClass*>(this)->*Delegate)();//вызов пользовательского метода
    }
};

class AnyClass
{
public:
    AnyClass()
    {
        std::cout << "AnyClass ctor" << std::endl;
    }
    void do_some_staff()
    {
        std::cout << "do some staff" << std::endl;
    }
    void operator () ()
    {
        std::cout << "operator ()" << std::endl;
    }
};

typename tool_table_wrapper<AnyClass, &AnyClass::do_some_staff> TAnyClass;//вызываем ф-ю do_some_staff
typename tool_table_wrapper<AnyClass> TAnyClass2;//используется параметр по умолчанию

TAnyClass* inst = new TAnyClass();
TAnyClass2* inst2 = new TAnyClass2();

этот код выведет:
Цитата

AnyClass ctor
do some staff
AnyClass ctor
operator ()


как видишь можно вызвать любой код, и это не сломается при переносе на другую платформу

Это сообщение отредактировал(а) Lazin - 8.9.2008, 09:38
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 7.9.2008, 17:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

я отвечу.


Эта фраза (уволили) относилась к другому коду, не к последней реализации. 

А из конструктивного хочу знать, где именно зависимость от компилятора (BCB - VS)? У кого VS под рукой, проверьте!



Это сообщение отредактировал(а) vaddsm - 7.9.2008, 17:43
PM MAIL   Вверх
Lazin
Дата 7.9.2008, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vaddsm @  7.9.2008,  17:37 Найти цитируемый пост)
Как по вашему указатель на метод класса соотносится с экземпляром класса, такой указатель как минимум должен содержать this и адрес самого метода в памяти. 

то что ты описал относится не к указателю на метод, а к указателю на метод с модификатором __closure, тоесть это работает только с BCB
для всех остальных компиляторов указатель на метод, это указатель на функцию, никакого this там не будет
PM MAIL Skype GTalk   Вверх
vinter
Дата 7.9.2008, 17:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



__fastcall


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 17:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

1. Куча макросов, код тяжело читать.


Макросы, тотже код, читать тяжело с непривычке. Так, что это субъективно.

Цитата

2. Код -  костыль, не то что палтформо - а компиляторо зависим.


Тут я жду как он себя на VS проявит, пока нет под рукой этого компилятора. Будет результат, тогда и поговорим.

Цитата

3. Мне сходу не понятно, что делает втой код, и не факт что я бы быстро вьехал, если бы не знал. Это показатель, для меня.


Тут я стобой и спорить не буду, для меня тоже показатель. Но в данном случае код достаточно снабдить и комментом.

Добавлено @ 17:51
Сейчас с VS разберемся.

Добавлено @ 17:54
Lazin, тот код что ты привел, он какое отношение к задаче имеет? Я уже устал повторять, задача не в том чтобы с делигатами работать было удобно. Задача сделать удобный интерфейс для библиотеки, в той форме, в которой я изначально показал.

Добавлено @ 17:56
ПОГОДИТЕ! а что VS не поддерживает конвенцию __fastcall???? Если поддерживает, в чем ваши притензии к коду?

Это сообщение отредактировал(а) vaddsm - 7.9.2008, 17:57
PM MAIL   Вверх
Lazin
Дата 7.9.2008, 18:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vaddsm @  7.9.2008,  17:48 Найти цитируемый пост)
в чем ваши притензии к коду?

в том, что он нерабочий smile 
жаль проверить нечем
PM MAIL Skype GTalk   Вверх
vaddsm
  Дата 7.9.2008, 18:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Lazin, у меня нет большого опыта, работы в VS среде, но ты берешся утверждать, что:

допустим, LPMF_CKINGFUNCTIONPTR - тип заведенный для хранения указателей на функцию член класса вида:

void Function_ofF_RINGTYPE(void);

тогда,  LPMF_CKINGFUNCTIONPTR lpFun = (LPMF_CKINGFUNCTIONPTR)&SomeClass->Function_ofF_RINGTYPE;

после этого lpFun не будет содержать никакой информаци о SomeClass???!

Добавлено @ 18:14
Цитата

в том, что он нерабочий  
жаль проверить нечем


 smile  smile  smile  


У меня он работает при любых интересующих меня условиях, я его писал и проверял.

Ты не проверял, но утверждаешь что он не рабочий. Говорить догмами по моему, это привилегия бога.

 smile Уважаемый, Lazin, прошу вас на практике подтвердить хоть один тезис из всех ваших критикующих постов. Любой!

Меня ооочень интересует конструктивная критика.


Это сообщение отредактировал(а) vaddsm - 7.9.2008, 18:15
PM MAIL   Вверх
vinter
Дата 7.9.2008, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  7.9.2008,  18:48 Найти цитируемый пост)
а что VS не поддерживает конвенцию __fastcall?

поддерживает, но не так как BCB
Цитата

In Fast Calling Convention (__fastcall), the first two parameters are loaded into ecx, edx registers, respectively.




--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 18:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Добрался до VS, сейчас доработаю.

Добавлено через 1 минуту и 7 секунд
Ага, vinter, вот это я и называю конструктивно, спасибо!
PM MAIL   Вверх
Lazin
Дата 7.9.2008, 18:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(vaddsm @  7.9.2008,  18:09 Найти цитируемый пост)
допустим, LPMF_CKINGFUNCTIONPTR - тип заведенный для хранения указателей на функцию член класса вида:

void Function_ofF_RINGTYPE(void);

тогда,  LPMF_CKINGFUNCTIONPTR lpFun = (LPMF_CKINGFUNCTIONPTR)&SomeClass->Function_ofF_RINGTYPE;

после этого lpFun не будет содержать никакой информаци о SomeClass???!

lpFun не будет содержать никакой информации об экземпляре SomeClass, мало того LPMF_CKINGFUNCTIONPTR lpFun = (LPMF_CKINGFUNCTIONPTR)&SomeClass->Function_ofF_RINGTYPE не скомпилируется
если имелось ввиду вот это
LPMF_CKINGFUNCTIONPTR lpFun = &SomeClass::Function_ofF_RINGTYPE;
то вызывать lpFun нужно будет не так, как это делается в builder, для методов с __closure:
Код

lpFun();

а так как это делают в С++:
Код

SomeClass inst;//экземпляр класса
typedef (SomeClass::*mem_func_type)();
mem_func_type lpFunc = &SomeClass::method;//указатель на метод
(inst.*lpFun)();//вызов функции

конструктивная критика:
щито такое __fastcall (); в теле класа?
Код

    lpCallMethod lpfun = ClassName::CallMethod;                
    TMyLib *Lib = new TMyLib(*(DWORD *)&lpfun); //<--

PM MAIL Skype GTalk   Вверх
vaddsm
  Дата 7.9.2008, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Итак, я в отладчике )! Насчет ecx, ваша, правда. push ebp, mov ebp, esp, как я и писал, все тоже. Смотрим дальше...
PM MAIL   Вверх
mes
Дата 7.9.2008, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  7.9.2008,  18:28 Найти цитируемый пост)
щито такое __fastcall (); в теле класа?

__fastcall это (компиляторозависимое) соглашение о вызове, указывающая компилятору, что некоторые из параметров будут 
будут переданы не через стек, а прямо через регистры

Добавлено через 1 минуту и 8 секунд
http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%...%BE%D0%B2%D0%B0

Это сообщение отредактировал(а) mes - 7.9.2008, 18:51


--------------------
PM MAIL WWW   Вверх
vinter
Дата 7.9.2008, 19:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(mes @  7.9.2008,  19:50 Найти цитируемый пост)
_fastcall это (компиляторозависимое) соглашение о вызове, указывающая компилятору, что некоторые из параметров будут

не не ен, он имеет ввиду, что значит 
Код

__fastcall  ()
 {
  MessageBox(0, message, "Trick! ;)))", 0);
 };
вот это.
если я правильно понял.

Цитата(vaddsm @  7.9.2008,  19:46 Найти цитируемый пост)
 push ebp, mov ebp, esp, как я и писал, все тоже

ясен пень, это стандарные дейстивия, необходимые для возврата из процедуры.



--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 7.9.2008, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(mes @  7.9.2008,  18:50 Найти цитируемый пост)
__fastcall это

оп я не на то ответил )
__fastcall () - насколько я понял это перегрузка оператора инициализации объекта в борланде.
то есть new Class(); // <- вот тут вызывается..

Это сообщение отредактировал(а) mes - 7.9.2008, 19:12


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

ясен пень, это стандарные дейстивия, необходимые для возврата из процедуры.


Возможна реализация компилятора, в которой данне действия будут выполнятся иначе и тогда код в на таком компиляторе станет не деиспособен, вобщем то на VS он тоже пока не работает, но погодите еще немного, сейчас внесем необходимые инструкции .
PM MAIL   Вверх
vinter
Дата 7.9.2008, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(mes @  7.9.2008,  20:11 Найти цитируемый пост)
__fastcall () - насколько я понял это перегрузка оператора инициализации объекта в борланде.

так погоди, тут вызывается конструктор. Что еще за оператор инициализации? smile 


--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 7.9.2008, 19:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vinter @  7.9.2008,  19:30 Найти цитируемый пост)
ак погоди, тут вызывается конструктор. Что еще за оператор инициализации? smile  

конструктор вызовется и без ()


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


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(mes @  7.9.2008,  20:32 Найти цитируемый пост)
конструктор вызовется и без ()

естественно, () это необязательная добавка. Впервые слышу об операторах инициализации.


--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 7.9.2008, 19:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vinter @  7.9.2008,  19:35 Найти цитируемый пост)
естественно, () это необязательная добавка.

Ну вот судя по всему борланд и положил на нее глаз ))



--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 7.9.2008, 20:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

ясен пень, это стандарные дейстивия, необходимые для возврата из процедуры.


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


Сделал реализацию совместимую с VS и BCB, сейчас код выложу. Да комиляторозависимо, но это всеголишь интерфес к библиотеке, сама либа представлена набором функций, и если пользователь не может в силу несовместимости пользоваться простой конструкций, он сможет работать с функциями напрямую. 

Это сообщение отредактировал(а) vaddsm - 7.9.2008, 20:45
PM MAIL   Вверх
mes
Дата 7.9.2008, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  7.9.2008,  20:44 Найти цитируемый пост)
Таки уж и стандартные? Стандарт - это язык, а то как, тот или иной производитель компилятора, представляет его в машином коде, это сугубо его личное дело. 

Стандарты бывают разные. В данном случае шла речь о стандарте соглашений вызова.
тут немного замутняет картину то, что используется __fastcall - a oно компиляторозависимое соглашение. 



--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 8.9.2008, 01:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ужос ___х!  smile  Дело в том что конвенции эти судя по тому, что каждый компилятор интерпритирует их в вольной форме для методов, разработаны для внешних функций а не для методов класса. Если понятно о чем я говорю... Например, стандартный __cdecl, родной для C, борланд помещает аргументы в стек, последним в стек идет this, в тоже время Microsoft, разместив аргументы в стеке, this передает через ecx. Для __stdcall соответственно. Почему об это я заговорил, по тому, что от конвенции зависит где именно в стеке будет this, после EBP или до. Тут все не так просто, развертывая стек надо еще смотреть, а что именно за метод по вызову. Сейчас дорабатываю.
PM MAIL   Вверх
vaddsm
Дата 8.9.2008, 02:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Точто могу сказать одно, на консрукторы  в VS конвенции не распростроняются, что непеши всегда аргументы в стек, this в ecx.

Это сообщение отредактировал(а) vaddsm - 8.9.2008, 02:15
PM MAIL   Вверх
mes
Дата 8.9.2008, 02:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  8.9.2008,  01:59 Найти цитируемый пост)
конвенции эти судя по тому, что каждый компилятор интерпритирует их в вольной форме для методов, разработаны для внешних функций а не для методов класса

 smile ага, понятие метод есть только на уровне языка, в объектном файле они (методы) представлены в виде функций.


Это сообщение отредактировал(а) mes - 8.9.2008, 02:54


--------------------
PM MAIL WWW   Вверх
dumb
Дата 8.9.2008, 04:21 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


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

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



vaddsm, приведенный тобой кривой костыль не только непонятен/несопровождаем, но и зависим не только от компилятора, но и от опций, а именно: от stack frames и от оптимизации. выключи frames(а в release они по дефолту выключены) или включи оптимизацию - и аля-улю.
косяк, кстати:
Цитата(vaddsm @  7.9.2008,  18:16 Найти цитируемый пост)

...
   TMyLib *Lib;
   TMyLibInterface()
   {
    lpCallMethod lpfun = ClassName::CallMethod;
    TMyLib *Lib = new TMyLib(*(DWORD *)&lpfun);
   };
   ~TMyLibInterface()
   {
    delete Lib;
...


Цитата(vaddsm @  7.9.2008,  18:16 Найти цитируемый пост)
Прежде всего давайте рассмотри начало любой функции описанной средствами языка c++ в машинном коде:
Код
00426100 55                push ebp
00426101 8BEC            mov ebp,esp

как уже было упомянуто, формирование фрэймов в стэке зависит от опции(и от компилера).

Цитата(vaddsm @  7.9.2008,  18:16 Найти цитируемый пост)
Благодаря этому правилу мы всегда можем раскрутить стек и дойти до начала стека интересующей нас функции.

в общем случае можно только отсчитать н-ное кол-во фрэймов, и понадеяться, что вызовы шли именно так, как предполагалось.

Цитата(vaddsm @  7.9.2008,  18:16 Найти цитируемый пост)
Но так, как для выполнения этой операции нам потребуется один регистр, необходимо позаботится о том, чтобы его первоначальное значение не было утеряно

в данном случае никакой необходимости в этом нет.

Цитата(vaddsm @  7.9.2008,  18:16 Найти цитируемый пост)
Код
mov  eax, [eax-0x04]

Но в данном случае мы берем значение не из ячейки стека, в которой находится очередной EBP, а на 4 байта выше, именно туда функция – метод класса помещает указатель.

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

"боги", "гуру"... smile

Цитата(vaddsm @  8.9.2008,  02:59 Найти цитируемый пост)
Почему об это я заговорил, по тому, что от конвенции зависит где именно в стеке будет this, после EBP или до.
от соглашения зависит будет ли this помещен в стэк(до вызова метода) или нет. "после" - это особенности процесса компиляции.

Цитата(vaddsm @  8.9.2008,  02:59 Найти цитируемый пост)
Тут все не так просто, развертывая стек надо еще смотреть, а что именно за метод по вызову. Сейчас дорабатываю.
пелена начинает спадать...

Цитата(vaddsm @  7.9.2008,  21:44 Найти цитируемый пост)
и если пользователь не может в силу несовместимости пользоваться простой конструкций, он сможет работать с функциями напрямую.
чего ему и пожелаем, чтобы не ловить потом необъяснимые косяки.

PM MAIL   Вверх
vaddsm
  Дата 8.9.2008, 04:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



dumb, Спасибо, сейчас по пунктам отработаю приведенные вами замечания!

Вот пример, у меня работает при любом виде конструктора TAnyClass в средах BCB и VS. С опциями оптимизации, я пока не проработал. 

Код


class TMyLib
{

 public:

 void __fastcall DoSomeStuff(char *Ptr);

 TMyLib(DWORD dwCallAddr);
 ~TMyLib();

};

void __fastcall TMyLib::DoSomeStuff(char *Ptr)
{
 wsprintf(Ptr, "Action fired~!");
};


TMyLib::TMyLib(DWORD lpfn)
{

 __asm
 {

  push eax
  push ecx
  push ebx

  mov  eax, [ebp]  
  mov  eax, [eax]
  mov  ebx, [eax+0x04]
  mov  ebx, [ebx-0x08]
  xor  ecx, ecx
  mov  cl, bl

  cmp  ecx, 0x8B
  jnz  label_stdcall

  mov  ebx, [eax-0x04]
  jmp  label_call

  label_stdcall:

  mov  ebx, [eax+0x08]

  label_call:

  push ebx
  call lpfn
  pop  ebx

  pop  ebx
  pop  ecx
  pop  eax

 }

};

TMyLib::~TMyLib()
{

};

#define TOOL_TABLE_BEGIN(ClassName)                            \
                                                               \
 class TMyLibInterface                                         \
 {                                                             \
  public:                                                      \
   typedef void (__cdecl ClassName::*lpCallMethod)();          \
   TMyLib *Lib;                                                \
   TMyLibInterface()                                           \
   {                                                           \
    lpCallMethod lpfun = ClassName::CallMethod;                \
    Lib = new TMyLib(*(DWORD *)&lpfun);                        \
   };                                                          \
   ~TMyLibInterface()                                          \
   {                                                           \
    delete Lib;                                                \
   }                                                           \
 } MyLibInterface;                                             \
                                                               \
 public:                                                       \
                                                               \
 void __cdecl CallMethod()                                     \
 {                                                             
#define DO_ACTION(WITH) MyLibInterface.Lib->DoSomeStuff(WITH);
#define TOOL_TABLE_END                                         \
 };                                                            \
                                                               \
 protected:





class TAnyClass //: public TClass2
{


 protected:

 char message[50];

 TOOL_TABLE_BEGIN(TAnyClass)
 DO_ACTION(message)
 TOOL_TABLE_END

 public:

 TAnyClass ()
 {
  MessageBox(0, message, "Trick! ;)))", 0);
 };

 ~TAnyClass (){};

};



...

TAnyClass *x =  new TAnyClass();

Коменты будут.


P.S Права на чтение сегмента памяти не выставил, в следующем варианте будут.

Добавлено @ 04:44
В Борланде работает при любых опциях оптимизации. А в релизе пока нет.

Это сообщение отредактировал(а) vaddsm - 8.9.2008, 04:48
PM MAIL   Вверх
vaddsm
Дата 8.9.2008, 04:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



 smile ЛАЖА  smile 
PM MAIL   Вверх
Lazin
Дата 8.9.2008, 05:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



блин, так и не понял, зачем пихать ук. на функцию в DWORD? 
вместо
Код

TMyLib::TMyLib(DWORD lpfn)
{
 __asm
 {
  push eax
  push ecx
  push ebx
  mov  eax, [ebp]  
  mov  eax, [eax]
  mov  ebx, [eax+0x04]
  mov  ebx, [ebx-0x08]
  xor  ecx, ecx
  mov  cl, bl
  cmp  ecx, 0x8B
  jnz  label_stdcall
  mov  ebx, [eax-0x04]
  jmp  label_call
  label_stdcall:
  mov  ebx, [eax+0x08]
  label_call:
  push ebx
  call lpfn
  pop  ebx
  pop  ebx
  pop  ecx
  pop  eax
 }

вполне прокатит
Код

template<class T>
TMyLib::TMyLib(T& obj)
{
    obj.CallMethod();
 }

ведь ты вегда вызываешь один и тот-же метод в конструкторе, кстати, что будет, если пользователь в своем классе, захочет создать ф-ю с именем CallMethod? smile

Добавлено через 1 минуту и 39 секунд
Код

   TMyLib *Lib;                                                \
   TMyLibInterface()                                           \
   {                                                           \
    Lib = new TMyLib(*this);                        \
   }; 


PM MAIL Skype GTalk   Вверх
vaddsm
  Дата 8.9.2008, 10:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Lazin, CallMethod где? ГИДЕ? Он в TAnyClass, а ты this передаеш какой? На TMyLibInterface.

Цитата

если пользователь в своем классе, захочет создать ф-ю с именем CallMethod? 


Это пример, в реали этот метод будет называться, где-то так: 

void hey_guy_do_never_try_to_name_method_like_this_f_king_long_method_name(void);

 smile 

Короч, универсального решения той задачи, которую я ставил изначально нет, есть частные вполне рабочие реализации, но в жизни совершенно неприменимые. Так, что в утиль. А лучше отдельной статьёй как делать ненадо. Хотя я сейчас еще гляну, как коверкается код при оптимизации, мож че придумаю и на этот раз  smile )
PM MAIL   Вверх
Lazin
Дата 8.9.2008, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата

Lazin, CallMethod где? ГИДЕ? Он в TAnyClass, а ты this передаеш какой? На TMyLibInterface.

ну да, незаметил, кстати а ты this какой передаешь? конструктор TMyLibInterface явно не в курсе о this экземпляра TAnyClass...

Добавлено через 2 минуты и 13 секунд
собрал под vs2005, пришлось заменить lpCallMethod lpfun = ClassName::CallMethod; на lpCallMethod lpfun = &ClassName::CallMethod;
запускаю, валится на асм вставке, и debug и release...
PM MAIL Skype GTalk   Вверх
vaddsm
Дата 8.9.2008, 10:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Lazin, ) не обижайся, но ты жгешь.  smile  Зачем, весь этот асм если бы метод был описан TMyLibInterface. Я же по пунктам расписывал, как раскручивая стек мы получаем this TAnyClass. Но в последней реализации, там еще эмпирическим путем делается догадка о конвенции вызова метода, по тому какой опкод следует перед call TAnyClass() mov или push.

У меня в VS - шестерка работает, а вобщем-то забей. Продолжать в этом направлении что-то делать нет смысла, по тому, как я уже упоминал, стандартом является язык а не то как его конкретный компилятор представляет в машинном коде. Еще стандарт, конвенции вызовов функций, но здесь этого не достаточно.




PM MAIL   Вверх
Lazin
Дата 8.9.2008, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата

Lazin, ) не обижайся, но ты жгешь.
сам такой smile 
ты когда это писал, задумывался о том, что станет с твоим кодом, если пользователь, к примеру объявит хоть одну виртуальную функцию?

зы
раздел называется "С++ общие вопросы", для асма есть свой раздел
PM MAIL Skype GTalk   Вверх
W4FhLF
Дата 8.9.2008, 11:43 (ссылка) |    (голосов:5) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Цитата(vaddsm @  8.9.2008,  10:57 Найти цитируемый пост)
Lazin, ) не обижайся, но ты жгешь.


Без обид, но жжёшь по-моему тут один ты. Ради экономии нескольких строк придумывать такой неповоротливый костыль... Лучше снабди библиотеку хорошей документацией и примерами, и сделай всё в рамках стандарта. 


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
vaddsm
Дата 8.9.2008, 12:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата

ты когда это писал, задумывался о том, что станет с твоим кодом, если пользователь, к примеру объявит хоть одну виртуальную функцию?


Если клас будет унаследован от абстрактного или сам станет таковым после объявления виртуальных методов. То в самом начале, экземпляра подобного класса будет описываться VMT. А как это повлияет на алгоритм извлечения this? Конструктор то виртуалить нельзя. 

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

Добавлено через 6 минут и 42 секунды
Цитата

Без обид, но жжёшь по-моему тут один ты. Ради экономии нескольких строк придумывать такой неповоротливый костыль...


Темка, то как называлась... "Возможно ли ?". В целях самообразования между прочем. А то, что я предложил -- первый пришедший в голову, вариант. Верняк есть и другие, предложите свои.

Добавлено через 12 минут и 56 секунд
Цитата

Мраздел называется "С++ общие вопросы", для асма есть свой раздел


Серьезно?? и куда меня послали бы в этом разделе, с вопросом о выполнении кода при инициализации экземпляра объекта c++ класса. 

В лучшем случае в этот раздел.  smile 
PM MAIL   Вверх
Lazin
Дата 8.9.2008, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата

Если клас будет унаследован от абстрактного или сам станет таковым после объявления виртуальных методов. То в самом начале, экземпляра подобного класса будет описываться VMT. А как это повлияет на алгоритм извлечения this? Конструктор то виртуалить нельзя. 

я подумал что ты пытаешься определять адрес по другому... если его искать в стеке, до должно работать (для одного компилятора), но все равно это костыли...


Цитата

Серьезно?? и куда меня послали бы в этом разделе, с вопросом о выполнении кода при инициализации экземпляра объекта c++ класса.

дело в том, что многие (я например) не знают асм, а то, что ты пишешь не соответствует стандарту С++ и вообще не обязано(мягко говоря) работать


PM MAIL Skype GTalk   Вверх
mes
Дата 8.9.2008, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  8.9.2008,  10:13 Найти цитируемый пост)
Хотя я сейчас еще гляну, как коверкается код при оптимизации, мож че придумаю и на этот раз 

В любом случае такое решение получится одноразовым (непереносимым).
Я все таки считаю , что лучше смотреть в сторону  стандартных языковых возможностей. 
Вы можете привести пример желаемого взаимодействия клиентского кода с библиотекой без учета  реализации?

Это сообщение отредактировал(а) mes - 8.9.2008, 13:22


--------------------
PM MAIL WWW   Вверх
vaddsm
  Дата 8.9.2008, 14:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ладно, давайте забудем на время о методе, в адрес которого прозвучала критика. И так, как единогласно было решено – нормального, соответствующего стандартам, способа реализации того, что я хотел видеть – нет. 

Предложите свои:

Некоторая библиотека предоставляет свой функционал через методы класса TMyLib.

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

Код

TAnyClass()
{

 MyLib.Function(_ИМЯ_МЕТОДА1_, _ИМЯ_МЕТОДА2);
 MyLib.Function(_ИМЯ_МЕТОДА3_, _ИМЯ_МЕТОДА4);

}


Но, так, как библиотека задает поведение методов класса, устанавливает правила. Как если написать virtual или DYNAMIC перед методом, то было бы весьма логично эти правила описывать в том месте, где декларируются эти самые функции. То как я видел это, вы уже видели.






PM MAIL   Вверх
W4FhLF
Дата 8.9.2008, 14:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


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

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



Код

MyLib.Function(_ИМЯ_МЕТОДА1_, _ИМЯ_МЕТОДА2);


Что здесь происходит? Вызов _ИМЯ_МЕТОДА1_, а потом _ИМЯ_МЕТОДА2? Или просто сохранение их адресов? Как тогда потом это применяется? 

Цитата(vaddsm @  8.9.2008,  14:23 Найти цитируемый пост)
 так, как библиотека задает поведение методов класса, устанавливает правила.


Что значит задаёт поведение методов класса? Какие правила? 
Код метода статичен. Следовательно, на его поведение могут влиять только переменные-члены класса или аргументы при вызове. 

Или в библиотеке существует некоторый унифицированный интерфейс и TMyLib задаёт методы вызова, которые потом где-то кем-то вызываются? Если так, то где и кем? 

Я пытаюсь въехать в задачу smile



--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
mes
Дата 8.9.2008, 15:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  8.9.2008,  14:23 Найти цитируемый пост)
Самым простым способом применения, является вызов ее функций в конструкторе, класса для которого она применяется:

Это опять реализация... Пострайтесь именно о интерфейсе/функционале библиотеки рассказать.


Цитата(W4FhLF @  8.9.2008,  14:49 Найти цитируемый пост)
Я пытаюсь въехать в задачу smile

 smile  7я страница уже заканчивается, а основная задача до сих пор под покровом тайны  smile 


--------------------
PM MAIL WWW   Вверх
xvr
Дата 8.9.2008, 18:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Код

#define TABLE_DEF(Base) \
class CallMe { \
 Base* self; \
public: \
 CallMe() {self=(Base*)( ((char*)this)-offsetof(Base,my_class_instance)); self->call_whatever_you_need();} \
} my_class_instance;

class Test {
public:
TABLE_DEF(Test)

 void call_whatever_you_need();
};

Жуть конечно, но гораздо более переносимо, чем asm вставки   smile 


Это сообщение отредактировал(а) xvr - 8.9.2008, 18:31
PM MAIL   Вверх
vaddsm
  Дата 9.9.2008, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



ОГО!  smile, Понятия не имел о существовании такого макроса offsetof, пытался сделать другим способом подобное, но натыкался на грабли с выравнованием структуры. Это супер! До Вас тут яросно пытались доказать что невозможно это, кто-то даже про фортачку вспоминал, ну вот пускай сейчас туда сам лезит.  smile  Ох-р-и-неть! Круто! 

Надо успокоится. Теперь посути, какие недостатки видят участники форума в данном методе?, я лично считаю что код 100% рабочий и переносимый. 

Цитата

Что значит задаёт поведение методов класса? Какие правила? 


Если, честно я немного растерен, а зачем это собственно расказывать здесь, ведь это уже оффтопик.

Цитата

Код метода статичен. 


Статичен, до поры до времени.

Цитата

Следовательно, на его поведение могут влиять только переменные-члены класса или аргументы при вызове. 


Следовательно не так.

Цитата

7я страница уже заканчивается, а основная задача до сих пор под покровом тайны


Как я вижу, основная задача решена xvr. 

Цитата

Или в библиотеке существует некоторый унифицированный интерфейс и TMyLib задаёт методы вызова, которые потом где-то кем-то вызываются? Если так, то где и кем? 


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

Добавлено через 7 минут и 50 секунд
xvr, Умница!  smile  У меня при всех условиях работает верно. smile 
PM MAIL   Вверх
vaddsm
  Дата 9.9.2008, 00:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Причем, благодаря именно такой реализации мой код будет вызываться значительно раньше всего, что будет описано в конструкторе класса. И это мне тоже, очень надо!
PM MAIL   Вверх
mes
Дата 9.9.2008, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  9.9.2008,  00:07 Найти цитируемый пост)
xvr, Умница!  smile 

 smile  Поддерживаю.  +1


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 01:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Ага, поставьте +, будет 100 постов присоеденюсь! smile 
PM MAIL   Вверх
mes
Дата 9.9.2008, 02:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  9.9.2008,  01:20 Найти цитируемый пост)
Ага, поставьте +

Цитата(mes @  9.9.2008,  00:53 Найти цитируемый пост)
+1

уже поставил )


--------------------
PM MAIL WWW   Вверх
Lazin
Дата 9.9.2008, 05:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата(xvr @  8.9.2008,  18:30 Найти цитируемый пост)
Жуть конечно, но гораздо более переносимо, чем asm вставки 

ничего не заметили? smile 
PM MAIL Skype GTalk   Вверх
mes
Дата 9.9.2008, 09:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(Lazin @  9.9.2008,  05:38 Найти цитируемый пост)
ничего не заметили? smile  

ага, заметили.. ) никто и не оспаривает реальное его "жутие", однако это не преуменьшает заслуги xvr'a,
показавшего пример, который отвечает на вопрос темы. 


Это сообщение отредактировал(а) mes - 9.9.2008, 09:47


--------------------
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 11:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А жутие то в чем собственно? Чес слово, вот на asm - то действительно было жутие. Не тебе стандартов, не тебе переносимости. Мне бы хотелось понять каким критериям не удовлетворяет данный код?
PM MAIL   Вверх
vinter
Дата 9.9.2008, 11:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата(vaddsm @  9.9.2008,  12:05 Найти цитируемый пост)
 Мне бы хотелось понять каким критериям не удовлетворяет данный код?

читабельности


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Good
  • 1. читабельности
  • 2.


Продолжите список, пожалуйста.
PM MAIL   Вверх
vinter
Дата 9.9.2008, 11:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



Цитата

Because of the extended functionality of structs in C++, in this language, the use of offsetof is restricted to "POD types", which for classes, more or less corresponds to the C concept of struct (although non-derived classes with only public non-virtual member functions and with no constructor and/or destructor would also qualify as POD).

хм, получается что этот макрос на честном слове работает в этом случае?


--------------------
Мой блог
PM MAIL WWW   Вверх
vaddsm
Дата 9.9.2008, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Гляньте, как описан в различных компиляторах данный макрос:

Код

// Keil 8051 compiler
#define offsetof(s,m) (size_t)&(((s *)0)->m) 

// Microsoft x86 compiler (version 7)
#define offsetof(s,m) (size_t)(unsigned long)&(((s *)0)->m) 

// Diab Coldfire compiler
#define offsetof(s,memb) ((size_t)((char *)&((s *)0)->memb-(char *)0))


В борланде, первый вариант применяется. Решительно не понимаю, как подобная вешь может быть интерпретирована не правильно. Если компилятор всегда знает смещения членов класса (относительно начала класса), как подобный макрос может привести к ошибке? У меня работает верно и при наследовании и для абстрактных классов.

Гляньте статью, здесь рассмотрены другие варианты примененя этого макроса, ни слова о несовместимости с ПОД типами. http://www.embedded.com/columns/technicali...equestid=142048
PM MAIL   Вверх
Lazin
Дата 9.9.2008, 12:25 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3820
Регистрация: 11.12.2006
Где: paranoid oil empi re

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



Цитата

А жутие то в чем собственно? Чес слово, вот на asm - то действительно было жутие. Не тебе стандартов, не тебе переносимости. Мне бы хотелось понять каким критериям не удовлетворяет данный код?
  • он неясный, "explicit is better then implicit" и в том-же духе...
  • это не в стиле С++
  • макросы для изменения кода лучше не использовать, их принято использовать только для управления компиляцией, а не в качестве замены шаблонов
  • call_whatever_you_need - вызывается в то время, когда объект еще не сконструирован, то-есть функция будет вызвана тогда, когда для некоторых членов класса еще не-был вызван конструктор, единственный способ это обойти, размещать твой макрос в теле класса до объявления членов класса
я уже предлагал написать для пользовательского класса враппер, предложу еще раз,
допустим есть пользовательский класс:
Код

class my_test
{
public:
    int a_;
    std::string b_;
    my_test(int a, std::string& b) : a_(a), b_(b) {}
    std::string name()
    {
        return std::string("third");
    }
};

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

template<class T, class P, P T::*Value>
struct class_member
{
    static P& get(T& self)
    {
        return self.*Value;
    }
};

функция get шаблона получает this и возвращает требуемый член класса, то-же самое можно сделать и для функций:
Код

template<class T, class P, P (T::*Fn)()>
struct class_member_fn
{
    static P call(T& self)
    {
        return (self.*Fn)();
    }
};

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

template<class Derived, class Member>
class wrapper : public Derived
{
public:
    wrapper() : Derived() {}

    template <class P>
    wrapper(P p) : Derived(p) {print_base_member();}

    template <class P1, class P2>
    wrapper(P1 p1, P2 p2) : Derived(p1, p2) {print_base_member();}

    template <class P1, class P2, class P3>
    wrapper(P1 p1, P2 p2, P3 p3) : Derived(p1, p2, p3) {print_base_member();}

    template <class P1, class P2, class P3, class P4>
    wrapper(P1 p1, P2 p2, P3 p3, P4) : Derived(p1, p2, p3, p4) {print_base_member();}

    void print_base_member()
    {
        std::cout << Member::get(static_cast<Derived&>(*this)) << std::endl;
    }
};

первый параметр - пользовательский класс, второй параметр - член пользовательского класса, который нужен будет врапперу, если написать вот так,
Код

typedef wrapper<
            my_test, 
            class_member<my_test, int, &my_test::a_> 
> wrap_test;

то компилятор сгенерирует класс, который ведет себя так-же как и пользовательский, но при создании его экземпляра будет выполнен нужный нам код (в данном случае будет выведено значение члена класса, который передан в качестве параметра), так-же, в отличии от кода с макросами, врапперы можно объединять в цепочки и работать с произвольным набором параметров...
Код

typedef wrapper<
            wrap_test, 
            class_member<my_test, std::string, &my_test::b_> 
> double_wrap_test;

при создании экземпляра класса double_wrap_test будут выведены на экран оба члена класса my_test, далее, можно написать враппер для функций:
Код

template<class Derived, class Function>
class wrapper_fn : public Derived
{
public:
    wrapper_fn() : Derived() {}

    template <class P>
    wrapper_fn(P p) : Derived(p) {print_base_member();}

    template <class P1, class P2>
    wrapper_fn(P1 p1, P2 p2) : Derived(p1, p2) {print_base_member();}

    template <class P1, class P2, class P3>
    wrapper_fn(P1 p1, P2 p2, P3 p3) : Derived(p1, p2, p3) {print_base_member();}

    template <class P1, class P2, class P3, class P4>
    wrapper_fn(P1 p1, P2 p2, P3 p3, P4) : Derived(p1, p2, p3, p4) {print_base_member();}

    void print_base_member()
    {
        std::cout << Function::call(static_cast<Derived&>(*this)) << std::endl;
    }
};

который вызывает функцию пользовательского класса, если сделать так:
Код

typedef wrapper_fn<
            double_wrap_test,
            class_member_fn<my_test, std::string, &my_test::name>
> thriple_wrap_test;

то после создания объекта my_test, будут выведены параметры a_, потом b_, а потом то, что вернет функция name...
так-же можно перехватить момент удаления объекта, и самое приятное в этом, что компилятор теперь сам будет следить за корректностью кода, если я попытаюсь создать объект у которого конструктор принимает больше 4х параметров, код просто не скомпилируется, а не упадет....
когда работает код враппера, все данные пользовательского класса уже гарантировано сконструированы....

Добавлено через 13 минут и 57 секунд
Цитата

call_whatever_you_need - вызывается в то время, когда объект еще не сконструирован, то-есть функция будет вызвана тогда, когда для некоторых членов класса еще не-был вызван конструктор, единственный способ это обойти, размещать твой макрос в теле класса до объявления членов класса
вот тут я наврал, нужно размещать макрос не до объявления а после, так как переменные класса конструируются в порядке их объявления...
PM MAIL Skype GTalk   Вверх
vinter
Дата 9.9.2008, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Explorer
****


Профиль
Группа: Завсегдатай
Сообщений: 2735
Регистрация: 1.4.2006
Где: Н.Новгород

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



vaddsm, я честно говоря не совсем понимаю что написано в том предложении, оно какое то кривое. Но насколько я понял, там имеется ввиду, что ограничен в рабе с НЕ POD типами.. эта сцитата с C++ references, и я не вижу причин им не доверять. По всей видимости это несовсем\совсем не стандартная фича. Жаль стандарта нет под рукой...


--------------------
Мой блог
PM MAIL WWW   Вверх
mes
Дата 9.9.2008, 14:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(vaddsm @  9.9.2008,  11:05 Найти цитируемый пост)
Мне бы хотелось понять каким критериям не удовлетворяет данный код? 

вот пример опасного кода:

Код

class A
{
    public:

       A () : i(2) {}
       void f ()  { std::cout<<"A::f() "<<i << endl;  }
    private:
        int i;
};

class Test  {
public:
TABLE_DEF(Test)

 void call_whatever_you_need() { std::cout<<"call_... "<<i << endl;  p->f(); }

 Test() : i (5), p(new A) { }

 private:
  int i;
  A *p;
};





Это сообщение отредактировал(а) mes - 9.9.2008, 15:17


--------------------
PM MAIL WWW   Вверх
xvr
Дата 9.9.2008, 15:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

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



Цитата(mes @ 9.9.2008,  14:21)
Цитата(vaddsm @  9.9.2008,  11:05 Найти цитируемый пост)
Мне бы хотелось понять каким критериям не удовлетворяет данный код? 

вот пример опасного кода:

Код

class A
{
   public: 
    void f() { std::cout << "test"; }
}
class Test  {
public:

TABLE_DEF(Test)
 void call_whatever_you_need() { p_a->f();};

 Test() : p_a (new A) { }
 ~Test() { delete p_a; }

 private:
  A* p_a;
};


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

Вполне определено - Segmentation Fault  smile Большие грабли этого метода (не считая использования offsetof) это требование размещать макрос TABLE_DEF после описания всех остальных полей класса, причем это не контролируется (в принципе)  smile Так что вариант от Lazin с wrapper лично мне нравится больше собственного (за что ему счас +1 поставлю  smile )

PM MAIL   Вверх
mes
Дата 9.9.2008, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(xvr @  9.9.2008,  15:05 Найти цитируемый пост)
это требование размещать макрос TABLE_DEF после описания всех остальных полей класса, причем это не контролируется (в принципе) 

ага.. это требование гораздо более опасно и трудно выполнимей, чем заставлять юзера добавлять строчку в конструктор )

Добавлено через 1 минуту и 59 секунд
Цитата(xvr @  9.9.2008,  15:05 Найти цитируемый пост)
Так что вариант от Lazin с wrapper лично мне нравится больше собственного (за что ему счас +1 поставлю  smile )

ага .. вариант с wrapper определено самый функциональный, переносимый и самое главное  безопасный

Это сообщение отредактировал(а) mes - 9.9.2008, 15:14


--------------------
PM MAIL WWW   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
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.3052 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


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

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