LINUX.ORG.RU
ФорумTalks

вопрос по с++


0

0

объясните смысл виртуальных функций

допустим имеем

class A{ //... public

virtual void a() =0; };

class B:public A {

public void a(){}; };

в классе b мы ведь с тем же успехом можем объявить метод а, даже если она не объявлена виртуальной в классе A

anonymous

Если мы имеем указатель (или референцию) на базовый класс A за которым находится класс B, и вызовем функцию a(), то будет вызвана именно функция в дефениции B для указываемой инстанции, если функция не виртуальная, то будет вызвана дефиниция с базового класса.

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

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

linux_newbe
()

> в классе b мы ведь с тем же успехом можем объявить метод а, даже если она не объявлена виртуальной в классе A

Зато ты можешь объявить функцию, которая берет указатель или ссылку на A, и вызывает для нее a(). Тогда ей можно будет передать B или любой другой объект класса, унаследованного от A. Почитай про жабские интерфейсы, скажем =)

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

2linux_newbe: тут речь шла не просто о виртуальных функциях, а об абстрактных ("pure virtual" в терминологии C++) - посмотри на его код...

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

>Почитай про жабские интерфейсы, скажем

очень даже правильно!

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

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

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

Абстрактные классы vs интерфейсы - это старая разборка =) С чисто практической точки зрения, при наличии множественного наследования (особенно грамотно реализованного, как, например, в Eiffel) интерфейсы не нужны. С теоретической - спорный вопрос. можно пофле^H^H^H^H^Hобсудить =)

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

> > при наличии множественного наследования... интерфейсы не нужны

> полностью согласен ;)

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

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

>Абстрактные классы vs интерфейсы - это старая разборка =) С чисто практической точки зрения, при наличии множественного наследования (особенно грамотно реализованного, как, например, в Eiffel) интерфейсы не нужны. С теоретической - спорный вопрос. можно пофле^H^H^H^H^Hобсудить =)

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

Другое дело, что в C++ часто не отделяют контракты от реализации (это соответствует "обычному" использованию класса), когда контракт описывается вместе с деталями реализации (приватные поля, например).

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

В C++ такого стимула нет :) И получается, что используя (ссылаясь на них) класс с полями мы делаем зависимость от нестабильной сущности (класс с полями - сущность нестабильная, так как реализация по определению нестабильна).

То есть интерфейс - это явная реализация понятия "контракт", и ничего больше. Класс в C++ - это реализация нескольких понятий (это и "реализация", и "контракт"), что, вообще говоря, может запутать (и путает) неопытных программистов.

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

P.S. Неохота работать в пятницу :)

P.P.S. А чем особенно множественное наследование в Eiffel?

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

> То есть интерфейс - это явная реализация понятия "контракт", и ничего больше. Класс в C++ - это реализация нескольких понятий (это и "реализация", и "контракт"), что, вообще говоря, может запутать (и путает) неопытных программистов.

Да, я это и имеел в виду, когда говорил, что теоретически не все так просто =)

> А чем особенно множественное наследование в Eiffel?

Отсутствием такой кривости дизайна как virtual base classes (во всяком случае, явно - я не знаю, как там "под капотом" оно сделано), и гибкостью в плане выбора наследуемых членов класса и возможностью их выборочного переопределения/переименования. См http://archive.eiffel.com/doc/online/eiffel50/intro/language/tutorial-10.html...

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

нда блин, жестокая вещь с++, пойду курить мануалы

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