Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / virtual methods / 25 сообщений из 356, страница 1 из 15
21.05.2018, 23:01
    #39647793
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Уважаемые коллеги объясните плиз

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
class A {
public :
    virtual void m() {
        std::cout << "A\n";
    }

    virtual ~A() {
        std::cout << "~A\n";
    }
};

class B : public A {

public :
    void m() override {
        std::cout << "B\n";
    }

    virtual ~B() {
        std::cout << "~B\n";
    }
};

class C : public B {

public :
    void m() override {
        std::cout << "C\n";
    }

    virtual ~C() {
        std::cout << "~C\n";
    }
};

int main() {
    A *o = new C();
    o->m();
    delete o;
}



Почему
- нет ругани на override без ключевого слова virtual ?
- почему даже не будучи virtual o->m(); все равно дергает метод класса С

Я все время думал что если метод невирутальный то A o дернет метод на классе А.

Поясните плиз тогда зачем вообще оверрайдить метод и снова делать его виртуальным - если вызов и так будет корректным.
...
Рейтинг: 0 / 0
21.05.2018, 23:19
    #39647795
AlekseySQL
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semen, давай по порядку появления в языке.

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

2. Поэтому в С++11 это "расшили": появилось необязательное (?) ключевое слово override: теперь оно показывает общий интерфейс с базовым классом, а слово virtual- возможность иметь общий интерфейс с производным классом.
...
Рейтинг: 0 / 0
21.05.2018, 23:22
    #39647796
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semen,

потому что оверрайд имеет приоритет над виртуализацией
...
Рейтинг: 0 / 0
22.05.2018, 00:16
    #39647804
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Потому что virtual необязателен в наследнике. Если метод объявлен virtual в предке то он в наследнике тоже virtual.
...
Рейтинг: 0 / 0
22.05.2018, 00:23
    #39647805
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semenЯ все время думал что если метод невирутальный то A o дернет метод на классе А.

У тебя метод m - виртуальный. Каким местом ты думал иначе - непонятно.
http://en.cppreference.com/w/cpp/language/override
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.05.2018, 05:20
    #39647830
CEMb
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Так как А объявлен с виртуальным методом, все его потомки будут иметь таблицу виртуальных функций, и там будет m(){}.

Dimitry SibiryakovУ тебя метод m - виртуальный. Каким местом ты думал иначе - непонятно.Класса В у него содержит тот самый метод, но не виртуальный, может поэтому и думал?
...
Рейтинг: 0 / 0
22.05.2018, 07:05
    #39647836
NekZ
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Siemarglsemen.s.semen,

потому что оверрайд имеет приоритет над виртуализацией
Это вообще о чём???
...
Рейтинг: 0 / 0
22.05.2018, 09:40
    #39647904
Siemargl
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
NekZSiemarglsemen.s.semen,

потому что оверрайд имеет приоритет над виртуализацией
Это вообще о чём???Неверно выразился - если оверрайд, то обязательно и виртуальный тоже.

Ссылка на стандарт на 2 поста выше.
...
Рейтинг: 0 / 0
22.05.2018, 10:47
    #39647932
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
SiemarglНеверно выразился - если оверрайд, то обязательно и виртуальный тоже.

Ссылка на стандарт на 2 поста выше.
Если удалить из программы все override то суть программы не изменится.
Это просто такой static_assert для виртуальных функций.

А так все правильно
...
Рейтинг: 0 / 0
22.05.2018, 11:04
    #39647940
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semen, в общем-то, тебе здесь всё, более-менее, расписали, но я рекомендую тебе рассмотреть свой пример с точки зрения ABI:
1. Компилятор создает три таблицы виртуальных методов для классов A, B и C;
2. В vtable класса A у тебя указатель на "void m()" и указатель на деструктор ~A();
3. В vtable класса B у тебя переопределённый для класса B указатель на "void m()", указатель на ~A() и указатель на ~B();
4. В vtable класса C у тебя переопределённый для класса C указатель на "void m()", указатель на ~A(), указатель на ~B() и указатель на ~C();
5. Создавая экземпляр класса C, первым элементом экземпляра класса, доступным по возвращаемому оператором new указателю, является указатель на таблицу виртуальных методов класса C и никакое стандартное приведение типов его не изменит. Изменить поведение виртуальных функций экземпляра класса можно ( это грязный хак ) только изменив указатель на таблицу виртуальных методов другого класса, например на указатель к VTABLE класса A, но, во-первых, для этого необходимо иметь экземпляр класса A в качестве источника, а во-вторых, при попытке разрушить такой объект, не отработают деструкторы ~C() и ~B(), которые должны освободить ресурсы, захваченные конструкторами при создании экземпляра класса C (в твоём вырожденном примере, конструкторы классов никакие ресурсы, типа памяти из кучи, не захватывают);

Это тебе для баловства (сделай trace в отладчике):
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
  typedef void (*PMethodProto)(void*);  // -- (void*) - неявный параметр this
  A* a = new A();
  C* c = new C();
  PMethodProto **pVTBL = reinterpret_cast<PMethodProto**>(c);
  (*pVTBL)[0](pVTBL);
  *pVTBL = *reinterpret_cast<PMethodProto**>(a);
  (*pVTBL)[0](pVTBL);
  delete c;

;-)
...
Рейтинг: 0 / 0
22.05.2018, 11:11
    #39647946
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Всем спасибо
...
Рейтинг: 0 / 0
22.05.2018, 11:15
    #39647947
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Кстати а если у класса A виртуальный деструктор - то что будет если у B,С будут невиртуальные деструкторы ?
...
Рейтинг: 0 / 0
22.05.2018, 11:17
    #39647951
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semenКстати а если у класса A виртуальный деструктор - то что будет если у B,С будут невиртуальные деструкторы ?Тебе надо будет дёрнуть деструктор ~B вручную из ~C. Что мешает попробовать?
...
Рейтинг: 0 / 0
22.05.2018, 12:01
    #39647999
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
[offtop]
Ну что, форумяне, теперь вы согласитесь со мной, что для лучшего понимания - как всё работает, изучение программирования лучше начинать с ассемблера и ABI ?
...
Рейтинг: 0 / 0
22.05.2018, 12:20
    #39648022
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semenКстати а если у класса A виртуальный деструктор - то что будет если у B,С будут невиртуальные деструкторы ?
Если в предке виртуальный, то неважно уже что там в наследниках - они уже по-любому виртуальные.
rdb_devТебе надо будет дёрнуть деструктор ~B вручную из ~C. Что мешает попробовать?
Не надо.
rdb_devНу что, форумяне, теперь вы согласитесь со мной, что для лучшего понимания - как всё работает, изучение программирования лучше начинать с ассемблера и ABI ?
Это не всем помогает, как видно
...
Рейтинг: 0 / 0
22.05.2018, 12:27
    #39648030
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Anatoly Moskovsky,

Спасибо
...
Рейтинг: 0 / 0
22.05.2018, 12:33
    #39648040
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
rdb_devТебе надо будет дёрнуть деструктор ~B вручную из ~C.

Не надо.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.05.2018, 12:37
    #39648046
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Деструкторы родителя дергаются автоматически

Это я вчера еще прочитал
...
Рейтинг: 0 / 0
22.05.2018, 12:39
    #39648048
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semenДеструкторы родителя дергаются автоматически

Это если ты уничтожаешь потомка по ссылке на потомка. При уничтожении потомка по ссылке на
родителя есть варианты.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.05.2018, 12:40
    #39648050
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Dimitry Sibiryakovsemen.s.semenДеструкторы родителя дергаются автоматически

Это если ты уничтожаешь потомка по ссылке на потомка. При уничтожении потомка по ссылке на
родителя есть варианты.


Расскажите поподробнее плиз
...
Рейтинг: 0 / 0
22.05.2018, 12:47
    #39648058
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Dimitry SibiryakovЭто если ты уничтожаешь потомка по ссылке на потомка. При уничтожении потомка по ссылке на
родителя есть варианты.
Если деструктор предка виртуальный то все работает как надо, неважно как удалять.
А виртуальный деструктор предка вообще-то нужно делать всегда если есть виртуальные функции.
...
Рейтинг: 0 / 0
22.05.2018, 13:03
    #39648073
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Anatoly MoskovskyЕсли в предке виртуальный, то неважно уже что там в наследниках - они уже по-любому виртуальные.
rdb_devТебе надо будет дёрнуть деструктор ~B вручную из ~C. Что мешает попробовать?Не надо.Ну, забыл я про этот нюанс! Даже не обратил внимания на подсказки IDE NetBeans - значки переопределения на полях.
...
Рейтинг: 0 / 0
22.05.2018, 13:08
    #39648079
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
Anatoly MoskovskyА виртуальный деструктор предка вообще-то нужно делать всегда если есть виртуальные функции.

Да. Но не все это помнят и не все версии компиляторов об этом предупреждают.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
22.05.2018, 13:08
    #39648080
rdb_dev
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
semen.s.semenА понтов то понтов Где ты увидел, что я понтуюсь? :)
Неужели тебе был бесполезен мой пример с указателями на таблицы виртуальных методов?
...
Рейтинг: 0 / 0
22.05.2018, 13:12
    #39648083
semen.s.semen
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
virtual methods
rdb_devsemen.s.semenА понтов то понтов Где ты увидел, что я понтуюсь? :)
Неужели тебе был бесполезен мой пример с указателями на таблицы виртуальных методов?

Ну ты отправил меня чего то там проверять вместо того чтобы корректно разобраться

Это я называю понтами

Я и так вчера запускал код и видел как работают деструкторы

Интересно было пообщаться с экспертами
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / virtual methods / 25 сообщений из 356, страница 1 из 15
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]