Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.07.2015, 17:14   #11
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

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

Можете почитать на досуге:
https://en.wikipedia.org/wiki/Singleton_pattern
waleri вне форума Ответить с цитированием
Старый 18.07.2015, 00:10   #12
robix
Пользователь
 
Регистрация: 16.07.2015
Сообщений: 31
По умолчанию

Все-таки насчет конструктора при вызове static функции хотелось уточнить. Я не сказал сразу. static функция EDU::Work (...) использует шаблон template <class T>
И из нее вызывается другая не static-функция, этого же класса которая в свою очередь обращается к переменным класса как на запись, так и на чтение и некоторые переменные уже должны быть проинициализированы, когда до них вызов доходит. Получается, что к этому моменту уже должен быть вызван конструктор ?
Вызывается так:

reinterpret_cast<T*>(history->user)->DoWork(......);

где DoWork не статичная функция моего класса EDU, вызванная из статичной EDU::Work (...) , T* - это некий другой класс, который дочерний от моего EDU. Т.е. вместо шаблона class History : public EDU,
history->user это данные внешней никак структуры не связанной с моим классом EDU.
Может быть тут каким то чудесным образом создается объект моего класса и вызывается конструктор через объект дочернего класса History ?
p.s.
Объект дочернего класса History не создается до этого вызова. Получается, что в этом вызове все происходит. Я не до конца понимаю каким образом.
robix вне форума Ответить с цитированием
Старый 18.07.2015, 02:27   #13
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,331
По умолчанию

если history->user НЕ указывает на объект типа Т, то все красиво сломается.
А если указывает, то значит его кто-то создал.

https://msdn.microsoft.com/ru-ru/library/e0w9f63b.aspx
http://en.cppreference.com/w/cpp/lan...interpret_cast
http://habrahabr.ru/post/106294/
waleri вне форума Ответить с цитированием
Старый 18.07.2015, 04:04   #14
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Код:
class cclass
{
pivate:
    int weight;
public:
    int get_weight() const { return weight; }
    static void __stdcall static_foo(cclass& self, <arguments>);
};

void __stdcall cclass::static_foo(cclass& self, <arguments>)
{
    // this->weight = 70; /* fail */
    self.weight = 70; /* try */
}

/*
    Данный приём уместен, если
*/
typedef void (__stdcall *lpfn_static_foo)(cclass& self);

int main()
{
    cclass c;
    lpfn_static_foo iuuu = c.static_foo;
    iuuu(c);
    printf("%i\n", c.get_weight());
}
P.S.
Код:
reinterpret_cast<T*>(history->user)->DoWork(......);
тоже самое что
Код:
((T*)(history->user))->DoWork(......);
ничего тут не создаётся, просто поменяли тип указателя, который будет ссылаться на тот DoWork
Вообще
Код:
cclass::do_work()
работает везде в потомках, Вы вызываете функцию по адресу такому-то.
Если помог, тут весы есть , Вам не сложно, а мне приятно.

Последний раз редактировалось Perchik71; 18.07.2015 в 04:13.
Perchik71 вне форума Ответить с цитированием
Старый 19.07.2015, 14:46   #15
robix
Пользователь
 
Регистрация: 16.07.2015
Сообщений: 31
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
если history->user НЕ указывает на объект типа Т, то все красиво сломается.
А если указывает, то значит его кто-то создал.

https://msdn.microsoft.com/ru-ru/library/e0w9f63b.aspx
http://en.cppreference.com/w/cpp/lan...interpret_cast
http://habrahabr.ru/post/106294/

Спасибо. Теперь кажется я понял. Оказалось еще до этого было выполнено

history->user = reinterpret_cast<UINT32>(new T);
а потом, уже
reinterpret_cast<T*>(history->user)->DoWork(......);

Только я не понял, как можно ссылку на объект класса преобразовывать в UINT32 ?
Почитал, что UINT32 это структура. Не понимаю, что происходит именно при преобразовании этом.

p.s.
Если я создаю объект дочернего класса, и через него вызываю public функцию родительского класса, в которой идет обращение к его членам, то конструктор родительского класса вызывается?

Последний раз редактировалось robix; 19.07.2015 в 14:50.
robix вне форума Ответить с цитированием
Старый 19.07.2015, 19:21   #16
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Цитата:
Сообщение от robix Посмотреть сообщение
Только я не понял, как можно ссылку на объект класса преобразовывать в UINT32 ?
Цитата:
Сообщение от robix Посмотреть сообщение
Если я создаю объект дочернего класса, и через него вызываю public функцию родительского класса, в которой идет обращение к его членам, то конструктор родительского класса вызывается?
Память это некой адрес, а адрес число, так что почему бы и не преобразовать? в чём проблема?

никакой объект не строиться, он уже построен малышом на этапе создания.
Если помог, тут весы есть , Вам не сложно, а мне приятно.
Perchik71 вне форума Ответить с цитированием
Старый 19.07.2015, 20:29   #17
Krasiosoft
Форумчанин
 
Аватар для Krasiosoft
 
Регистрация: 01.06.2015
Сообщений: 497
По умолчанию

Цитата:
Сообщение от Perchik71 Посмотреть сообщение
Память это некой адрес, а адрес число, так что почему бы и не преобразовать?
Только рекомендую преобразовывать в void*, а не в UINT32, т.к. если потом нужно будет собирать 64-битную программу с этого кода, то будут проблемы.
Если помог, буду очень благодарен за Ваш отзыв (весы в левой нижней части сообщения).
Krasiosoft вне форума Ответить с цитированием
Старый 19.07.2015, 21:33   #18
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
Подмигивание

Цитата:
Сообщение от Krasiosoft Посмотреть сообщение
Только рекомендую преобразовывать в void*, а не в UINT32, т.к. если потом нужно будет собирать 64-битную программу с этого кода, то будут проблемы.
тупо int он тоже меняется
///
Лови рекомендашку
Если помог, тут весы есть , Вам не сложно, а мне приятно.

Последний раз редактировалось Perchik71; 19.07.2015 в 21:43.
Perchik71 вне форума Ответить с цитированием
Старый 21.07.2015, 11:51   #19
robix
Пользователь
 
Регистрация: 16.07.2015
Сообщений: 31
По умолчанию

Спасибо.
Подскажите, я правильно понял.
Допустим есть:
Class F_CLASS {......};
S_CLASS *S;

S = reinterpret_cast<S_CLASS>(new F_CLASS);

На более низком уровне S это некая запись в памяти, в которой есть информация о том, что это указатель, также о том на какой тип данных он указывает, и адрес на который она указывает.
Но по этому адресу в данный момент будет раположен объект класса F.

Примерно так?
robix вне форума Ответить с цитированием
Старый 21.07.2015, 18:11   #20
Krasiosoft
Форумчанин
 
Аватар для Krasiosoft
 
Регистрация: 01.06.2015
Сообщений: 497
По умолчанию

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

Многие думают, что класс на низком уровне, это что-то невероятное. Сейчас я попробую объяснить, что это не так. Допустим, у нас есть класс:

Код:
class F_CLASS {
public:
    int a,b;
    F_CLASS():a(10),b(20){}
    GetA(){return a;}
    GetB(){return b;}
};
И следующий код:

Код:
        ...
        F_CLASS *myClass;
        myClass = new F_CLASS;

        int a = myClass->GetA();
        int b = myClass->GetB();
        int a1 = myClass->a;
        int b1 = myClass->b;
        ...
Рассмотрим:
Код:
        int a = myClass->GetA();
        int b = myClass->GetB();
        int a1 = myClass->a;
        int b1 = myClass->b;
Этот код на низком уровне будет выглядеть как:

Код:
//  EBP-48 это myClass
//  EBP-4C это a
//  EBP-50 это b
//  EBP-54 это a1
//  EBP-58 это b1

// int a = myClass->GetA();
PUSH DWORD PTR SS:[EBP-48]     //  добавление в стек myClass (параметр функции GetA)
CALL Project1.@F_CLASS@GetA    //  вызов GetA
MOV DWORD PTR SS:[EBP-4C],EAX  //  запись результата функции GetA в переменную a

// int b = myClass->GetB();
PUSH DWORD PTR SS:[EBP-48]     //  добавление в стек myClass (параметр функции GetB)
CALL Project1.@F_CLASS@GetB    //  вызов GetB
MOV DWORD PTR SS:[EBP-50],EAX  //  запись результата функции GetB в переменную b

// int a1 = myClass->a;
MOV EAX,DWORD PTR SS:[EBP-48]  //  запись myClass в EAX
MOV ECX,DWORD PTR DS:[EAX]     //  запись в ECX DWORD'a, который лежит по адресу EAX (myClass)
MOV DWORD PTR SS:[EBP-54],ECX  //  запись ECX'a в переменную a1

// int b1 = myClass->b;
MOV EAX,DWORD PTR SS:[EBP-48]  //  запись myClass в EAX
MOV EDX,DWORD PTR DS:[EAX+4]   //  запись в EDX DWORD'a, который лежит по адресу EAX+4 (myClass+4)
MOV DWORD PTR SS:[EBP-58],EDX  //  запись EDX'a в переменную b1
Если посмотреть, что лежит в памяти по адресу EBP-48 (myClass), то мы увидим:

Код:
00415954  0A 00 00 00 14 00 00 00 1A 00 00 00 01 00 00 00
Но под наш класс выделено только 8 байт на две переменные (a и b), т.е:

Код:
00415954  0A 00 00 00 14 00 00 00
Это можно проверить с помощью: sizeof(F_CLASS)
Если помог, буду очень благодарен за Ваш отзыв (весы в левой нижней части сообщения).
Krasiosoft вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Вызов функции из класса mc13 Общие вопросы по Java, Java SE, Kotlin 11 08.02.2015 20:52
Вызов функции из одного класса кнопкой из другого класса lexflax Qt и кроссплатформенное программирование С/С++ 1 12.12.2014 21:48
Вызов глобальной функции из объекта класса Darthriddikc Общие вопросы C/C++ 3 22.12.2013 21:03
C# Вызов метода без создания объекта. Предотвращение изменения фокуса. Colder M Помощь студентам 3 03.05.2011 23:42
Вызов методов объекта из функции? jojahti Общие вопросы C/C++ 3 03.08.2009 16:57