LINUX.ORG.RU

В чем разница между разными способами в обращении ("->", «*.», «& *.» )

 


0

2

В чем разница между разными способами в обращении ("->", «*.», «& *.» ), и какой способ лучше в плане «скорости работы»?

RenderWindow* g_window;
    
if (g_window->isOpen()) { ... }
    
if ((*g_window).isOpen()) { ... }
    
if (((RenderWindow&) *g_window).isOpen()) { ... }

Строго никакой разницы.

intelfx ★★★★★
()

Первое и второе - никакой разницы. Собственно -> было введено для упрощения конструкции (*ptr).fn().
В третьем случае ты явно задаешь тип на который ссылается объект. Use сase: при наследовании иногда бывает нужно вызвать метод предка.

Kroz ★★★★★
()
Ответ на: комментарий от deep-purple

Так здесь нет приведений, компилирующихся в машкод

Deleted
()

Разница только в количестве букв.

ox55ff ★★★★★
()

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

anonymous
()

Если указатель — стрелочка. Если объект — точка. Остальное ненужно.

Deleted
()
Ответ на: комментарий от RazrFalcon

приведение user-defined типов(исключая преобразование вида derived& -> base& при одиночном наследовании)

Deleted
()
Ответ на: комментарий от Deleted

приведение user-defined типов(исключая преобразование вида derived& -> base& при одиночном наследовании)

Ну так, base_ptr + offsetof(parent_object) хотя компиляторы обычно размещают данные родительского обьекта вначале дочернего, так что offset = 0, и base_ptr == derived_ptr по значению указателя.

Т.е. бесплатно.

KennyMinigun ★★★★★
()
Ответ на: комментарий от KennyMinigun

исключая преобразование [...] при одиночном наследовании

base_ptr == derived_ptr

Но это же нифига не так, даже для типичной реализации

Deleted
()

Тру спецы делают только так:

void *isOpen_ptr = &RenderWindow::isOpen;
typedef bool(__attribute__((__thiscall__))_isOpen)(void *_this);
if ((_isOpen(isOpen_ptr))(g_window)) { ... }

SR_team ★★★★★
()
Последнее исправление: SR_team (всего исправлений: 2)

в третьем способе у тебя C-style cast, за который нонче в плюсах по рукам бьют. Лучше использовать (по мере убывания нужности):

  1. static_cast
  2. dynamic_cast
  3. const_cast
  4. reinterpret_cast

Причем присутствие последних 3 в программе — один из симптомов плохого дизайна (да, есть исключения, когда действительно надо). А вот C-style cast пытается сделать все виды каста по этому скрывает «преступления».

А вообще — этот твой «третий» сбособ — вовсе не отдельный способ а по просту вариация второго плюс каст (к ссылке). Т.е. если использовать православный static_cast то выглядит даже нелепо:

RenderWindow* g_window;

if (static_cast<RenderWindow&>(*g_window).isOpen()) { ... }

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от Deleted

Ой, я провтыкал слово «исключая» :)

Тогда да, в случае множественного наследования к указателю добавляется константа (вычисленная в compile-time). Не очень то и дорого.

KennyMinigun ★★★★★
()
Ответ на: комментарий от deep-purple

Без кастов само быстрое, не?

Большая часть кастов, не считая динамик каста - это компайл тайм, то есть никак не влияет на производительность.

Dudraug ★★★★★
()

Ни в чём, никакой разницы.

slovazap ★★★★★
()
Ответ на: комментарий от Deleted

Первое, что приходит в голову: Брюс Эккель, «философия С++», глава о множественном наследовании. Там рассказывается, почему множественное наследование - плохо. Хотя, также разбираются случаи, когда множественное наследование - допустимо.

next_time ★★★★★
()
Ответ на: комментарий от next_time

Там говорится о необходимости соблюдать некоторую осторожность при данном виде наследования и только. Но где в крестах немного мест, где это ненужно

Deleted
()
Ответ на: комментарий от Deleted

Да нет, там приводятся чёткие критерии когда это точно не нужно. 1) Нельзя обойтись инкапсуляцией 2) Вот прям надо наследовать. Если хотя бы одно из утверждений ложно - м.н. не нужно.

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

next_time ★★★★★
()
Ответ на: комментарий от next_time

Видимо, я не то нашёл.

Нельзя обойтись инкапсуляцией

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

Вот прям надо наследовать

Вот прям так и написано?

Deleted
()

Трындец! Плюсер элементарные вопросы задает.

Ты, батенька, хотя бы теорию для начала почитай!

// да будет проклят мудератор, банящий по IP!

anonymous
()

Последний - каст к конкретному типу указателя. Что в общем уже говнокод. Если тип объекта под указателем не соответствует тому к которому кастуют - будет плохо.

invy ★★★★★
()
Последнее исправление: invy (всего исправлений: 1)
Ответ на: комментарий от Kroz

Use сase: при наследовании иногда бывает нужно вызвать метод предка.

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

invy ★★★★★
()
Ответ на: комментарий от KennyMinigun

Тогда да, в случае множественного наследования

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

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

Интересное замечание. Спасибо. Но и логично: ведь для такого даункаста надо использовать vtable.

Ну и позволю себе заметить, что такой даункаст — не признак хорошего дизайна.

KennyMinigun ★★★★★
()
Ответ на: комментарий от Deleted

static_cast в большинстве случаев не бесплатный

В большинстве случаев он ровно аналогичен обращению к методу. А если обращений будет много, то с кастом может быть даже дешевле.

anonymous
()
Ответ на: комментарий от anonymous

может быть даже дешевле

Почему?

Deleted
()
Ответ на: комментарий от KennyMinigun

reinterpret_cast и const_cast для сишных либ без которых в крестах никуда.

dynamic_cast бывает полезным для дополнительных контрактов которые могут быть реализованы а могут не быть.

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

anonymous
()
Ответ на: комментарий от anonymous

reinterpret_cast ... для сишных либ

да

и const_cast для сишных либ

нет (в сишке тоже есть const).

сишных либ без которых в крестах никуда.

нет*

* по большей степени (потому что бывает еще адская корпо-проприетарщина, которую переписывать нерентабельно)

dynamic_cast бывает полезным для дополнительных контрактов которые могут быть реализованы а могут не быть.

Да, исключение. Но сильно зависит от продхода к дизайну (sic!).



Ну и касательно цепляния к словам:

Заявлять что это всё плохой дизайн довольно таки радикально.

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

В оригинале звучит довольно мягко:

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

Особенное внимание прошу обатить на слово «симптом».

KennyMinigun ★★★★★
()
Последнее исправление: KennyMinigun (всего исправлений: 2)
Ответ на: комментарий от KennyMinigun

Кстати, про const_cast: еще одно инсключение — это добавление/удаление volatile в местах с «ручной» оптимизацией (что, очевидно, редко надобно, особенно с std::atomic).

По хорошему, const_cast надо было назвать cv_cast, т.к. он манипулирует cv-qualifier (cv = const volatile).

KennyMinigun ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.