Russian Qt Forum
Ноябрь 23, 2024, 07:54 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: Прелестно  (Прочитано 22141 раз)
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #30 : Октябрь 01, 2014, 17:53 »

Так проще:

Код
C++ (Qt)
bool QUApplication::notify( QObject* o, QEvent* e )
{
...
case QEvent::KeyPress:
if( QWidget::keyboardGrabber() == w )   // keyboardGrabber статический же. :)
{
return w->QWidget::event( e );
}
...
}
 


Конечно было проще, если бы не
Код
C++ (Qt)
virtual bool QWidget::event(QEvent*)» is protected
Записан

Qt 5.11/4.8.7 (X11/Win)
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #31 : Октябрь 01, 2014, 17:58 »

Конечно было проще, если бы не
Код
C++ (Qt)
virtual bool QWidget::event(QEvent*)» is protected
А в QObject он паблик, я туда заглянул.
Записан
Bepec
Гость
« Ответ #32 : Октябрь 01, 2014, 18:35 »

Old - знать и не говорить, это подло по отношению к другим Веселый То, что мои слова до вашего разума не добились - не повод ехидничать, хотяя... Ваше право.
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #33 : Октябрь 01, 2014, 18:40 »

Old - знать и не говорить, это подло по отношению к другим Веселый
У нас прямо форум подлецов... 90% знают и не говорят... Улыбающийся
Там три строчки кода, может вам стоит с этим разобраться?
Записан
Bepec
Гость
« Ответ #34 : Октябрь 01, 2014, 19:12 »

Вырванных из контекста Улыбающийся Мб и стоит, я не знаю. Я вас собственно и спрашиваю, желая узнать Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #35 : Октябрь 01, 2014, 22:48 »

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

Цитировать
thiscall
Используется в компиляторах C++. Обеспечивает передачу аргументов при вызовах методов класса в объектно ориентированной среде. Аргументы передаются через стек, справа налево. Очистку стека производит вызываемая функция, то есть тот же самый stdcall. Указатель (this) на объект, для которого вызывается метод, записывается в регистр ECX.
© Вика
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #36 : Октябрь 01, 2014, 22:51 »

А там не сказано что делать, если у процессора нет регистра ecx? Улыбающийся
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #37 : Октябрь 01, 2014, 22:54 »

Я думаю, регистры есть примерно во всех архитектурах. Поинт в том, что врядли this передаётся через стэк - это медленно.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #38 : Октябрь 01, 2014, 22:56 »

ЗЫ: вам, кстати, должно быть известно, что архитектур, кроме х86, не существует http://msdn.microsoft.com/en-us/library/ek8tkfbw(v=vs.71).aspx Улыбающийся
Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #39 : Октябрь 02, 2014, 06:28 »

Я думаю, регистры есть примерно во всех архитектурах. Поинт в том, что врядли this передаётся через стэк - это медленно.
Да не принципиально как он передаётся (это все отдается на откуп abi конкретной платформы), главное что он передаётся в функцию в качестве параметра.
Я простым языком хотел объяснить, что метод это обычная функция с дополнительным параметром. Улыбающийся

P.S. Я очень часто пишу на форум с телефона, поэтому подробно расписывать у меня терпения не хватает. Улыбающийся
« Последнее редактирование: Октябрь 02, 2014, 06:36 от Old » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #40 : Октябрь 02, 2014, 06:51 »

Я думаю, регистры есть примерно во всех архитектурах. Поинт в том, что врядли this передаётся через стэк - это медленно.
Да не принципиально как он передаётся (это все отдается на откуп abi конкретной платформы), главное что он передаётся в функцию в качестве параметра.
Я простым языком хотел объяснить, что метод это обычная функция с дополнительным параметром. Улыбающийся

P.S. Я очень часто пишу на форум с телефона, поэтому подробно расписывать у меня терпения не хватает. Улыбающийся

Как в python, только не так открыто для программиста Улыбающийся
Записан

GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #41 : Октябрь 02, 2014, 09:43 »

Ну так что, кто-нибудь что-либо скажет насчёт этого?
Записан

Qt 5.11/4.8.7 (X11/Win)
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #42 : Октябрь 02, 2014, 10:00 »

Я простым языком хотел объяснить, что метод это обычная функция с дополнительным параметром. Улыбающийся

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

Вы пишите так, словно можно закладываться на работоспособность следующего кода:
http://rextester.com/RSDW27510


Код:
#include <iostream>
using namespace std;

struct Example
{
    // мы можем запустить этот метод не как метод, а как обычную свободную функцию
    void foo(int) { cout<<"Example::foo(int);\n"; }
};

int main()
{
    std::cout << "Hello, world!\n";
    
    typedef
        void(*Free)(Example*, int);
    typedef
        void(Example::*Method)(int);
    
    //для того, что бы запустить метод, как свободную функцию
    //нужно выполнить преобразования метода в свободную функцию
    
    Method m= &Example::foo;
    
    //для этого возьмем адрес функции-члена таким образом,
    //что бы компилятор забыл изначальный тип функции-члена
    //это позволит обойти защиту компилятора при некорректном
    //с точки зрения компилятора преобразовании типов функции-члена к функции
    void* proxy = (void*)&m;


    //теперь извлекаем объект обратно, преобразовывая его тип к типу функции
    Free f = *((Free*)proxy);
    
    Example ex;
    
    
    //теперь, если ваша теория верна, мы можем запустить функцию,
    //передав первым аргументом тот самый "не видимый" параметр this
    //а следом все прочие аргуметы
    f(&ex,10);  
}


Представленный выше код дает представление о том, чем на самом деле является функция-член.
А так же иллюстрирует принципиальную схему действий компилятора.

Однако, несмотря на то, что представленный код работает в большинстве случаев - он является UB.
И компилятор, который мне пришлось обмануть, что бы выполнить каст, не зря запрещает такой каст.

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

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

Но при этом компилятор закладывается на то, что программист не делает UB.
А значит он не делает преобразований типов, которые запрещено делать.

А значит можно изменить вызов так, что бы параметры прошли через регистры, или ещё каким то особым образом.


А это означает, что "хакнутый" указатель на свободную функцию теоретически может отказать в любой момент.


Компилятор запрещает данные касты, специально, что бы пользователи не могли закладываться на конкретную стратегию вызова.
Это поведение описывается в стандарте как unspecified behaviour.

Что означает: компилятор сгенерирует "правильный" код вызова функции-члена, но каким именно он будет - нельзя знать наверняка.
И это нужно компиляторам для того, что бы максимально развязать им руки в плане всевозможных оптимизаций

Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #43 : Октябрь 02, 2014, 10:03 »

Ну так что, кто-нибудь что-либо скажет насчёт этого?

Это UB

Считайте что вам просто повезло, что при одиночном наследовании указатель на vtable всегда лежит в начале объекта и совпали индексы функций в нем.

(примечание: вроде бы не гарантируется что это всегда будет именно так)

Код, который наглядно иллюстрирует возможные проблемы:
http://ideone.com/KPiDmR
http://ideone.com/z0bAgC

Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #44 : Октябрь 02, 2014, 10:05 »

Вы пишите об этом так, словно компилятор, встретив вызов функции-члена, генерирует код вызова обычной функции, передав в качестве первого аргумента - адрес объекта.
Вовсе нет. Улыбающийся
Посмотрите на начало обсуждения, я постарался просто объяснить, почему код ТС не падает.
Я не собирался вдаваться в подробные объяснения всех механизмов для всех возможных ABI. Это я оставил для самостоятельного изучения ТС.
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.236 секунд. Запросов: 23.