powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / К виртуальным функциям
25 сообщений из 106, страница 1 из 5
К виртуальным функциям
    #39408801
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте C:
Продолжаю изучать D&E BS и некоторые ранние статьи BS. Книга, как я и говорил ранее, великолепная, другой эпитет подобрать трудно. Объем нюансов возникающих при проектировании и разработке языка огромный, не буду их перечислять - те, для кого этот топик вероятно знакомы с ними, а даже если не знакомы, то лучше BS я все равно не напишу. У меня много вопросов, на мой личный взгляд это интересные, хорошие вопросы. И позже, я планировал сделать какую-то отдельную тему посвященную этой книге, но поскольку график слишком плотный, то я понимаю, что времени на это может просто не хватить, да и такие большие топики не всегда приветствуются, что возможно и правильно. Потому пока не время для "всех вопросов".

BS отдает виртуальным функциям центральную роль при программировании на С++ и именно реализация такого рода концепции является одним из главных шагов для рождения С++ из C with Сlasses. Выше нужно сделать акцент на слове "реализация", я намеренно не использовал слово "появление". Данный раздел я решил посвятить виртуальным функциям, уже несколько дней они не дают мне спокойно думать о чем-то другом. Точнее не они, а история их реализации в С++.

1. Пусть у нас была бы возможность повлиять на реализацию языка. Представьте, что вы встретили листинг (D&E, BS)

Код: 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.
class X
{
	int x;
public:
	virtual void copy(X* p)
	{
		x = p->x;
	}
};

class XX : public X
{
	int xx;
public:
	virtual void copy(XX* p)
	{
		xx = p->xx;
		X::copy(p);
	}
};

void f(X a, XX b)
{
	a.copy(&b);//1
	b.copy(&a);//2
}



Какой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное, почему? (вопрос не о том, как сейчас будет происходить обработка данного кода). При этом, было бы интересно узнать о ваших мыслях не в контексте того, что сейчас есть в С++, а в контексте того, что у вас есть C with Сlasses и вы планируете интегрировать к данному языку механизм виртуальных функций.

2. Как часто вы используете виртуальные функции в своих программах и как лично вы относитесь к данному механизму?
3. Считаете ли вы ослабление правил замещения для типа возвращаемого значения и для аргументов правильным решением? Интересно, если бы комитет не принял предложения об этом, каким образом были бы решены возможные проблемы(пример из теории компиляторов, метод clone в базовом и производных классах). Лично мне кажется, что это привело бы к изменениям в системе типов языка, что в конечном счете могло положительно сказаться на ней.

Было бы очень интересно узнать ваше мнение по данным вопросам:)
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408808
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury,

1) Когда я вижу a.xxx или a->xxx то я ожидаю, что вызовется xxx именно у того класса, на экземпляр которого указывает a (или сам им является). В С++ это так и есть для полей и виртуальных функций. А для обычных функций класса - нет, даже если наследник переопределил функцию.

2) виртуальные функции - это в сочетании с наследованием в С++ необходимый и достаточный инструмент для реализации концепции интерфейсов. Так что что почти в любой программе в которой больше одного модуля они используются.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408813
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryКакой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное,
почему?

Лично я бы ожидал, что ошибка компиляции возникнет ещё раньше, когда идёт переопределение
метода с другой сигнатурой. Но кое-кто при разработке языка пожадничал на явное указание
overload/override и в результате мы имеем отличное логово для багов.

PS: override таки появился в С++11 и лично я его использую повсеместно, где хочу именно
перекрыть метод.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408868
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury,

Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б"
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408885
teo609
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
" для рождения С++ из C with Сlasses"
20 лет назад я учился именно такому С++. Большинство фишек из 11,14, 17 версий уводят все дальше от этого базового уровня. Становясь более мощным, язык позволяет все более сложные концепции и приемы, это повышает требования к программистам, уменьшает их число, повышает порог вхождения, но от возможности выстрелить в ногу так и не избавляет полностью.
Мне кажется, что современный С++ можно рассматривать как ветку от базового, направленную в сторону расширения возможностей языка. И что есть потребность в языке, который был бы другой веткой от базового С++, в котором меньше было бы всяких возможностей в духе Алексндреску, но который был бы надежнее, но без реализации через виртуальную машину (как Java), с сохранением и производительности и возможностью работы с иерархиями классов. Одной из основных возможностей повышения надежности мне кажется контроль работы экземпляров классов только в своей памяти, иное - только через специальные атрибуты. Чтобы в ран-тайме можно было бы включить такой режим контроля, доступна только своя память (и аргументы функций как пример средства реализации возможностей программы). Мне кажется что такой "более надежный но менее навороченный С++/С_с_классами" лучше подошел бы для всяких десктопных приложений, чем Java или C#, например те же десктопные игровые клиенты. Не уверен, может быть Objective C несет в себе что-то такое, давно не смотрел в ту сторону, да и на Windows с ним проблемы, а больше ничего похожего вообще в голову не приходит.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408946
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
teo609,

Держи ,,,,,,,,,,,,

googlethis: dlang, golang, nimlang, rust
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39408972
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky
2) виртуальные функции - это в сочетании с наследованием в С++ необходимый и достаточный инструмент для реализации концепции интерфейсов. Так что что почти в любой программе в которой больше одного модуля они используются.

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

Виртуальные функции нужны только когда у вас в программе есть иерархии классов.

Кстати, я видел в сети предложение в стандарт для реализации в С++ множественной диспетчеризации в виртуальных методах, вот это была бы бомба!
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409124
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercury
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
class X
{
	int x;
public:
	virtual void copy(X* p)
	{
		x = p->x;
	}
};



Какой результат на ваш взгляд было бы логично ожидать в строчках 1, 2, и, самое главное, почему? (вопрос не о том, как сейчас будет происходить обработка данного кода). При этом, было бы интересно узнать о ваших мыслях не в контексте того, что сейчас есть в С++, а в контексте того, что у вас есть C with Сlasses и вы планируете интегрировать к данному языку механизм виртуальных функций.


По классике это должен был бы быть

Код: plaintext
1.
virtual X& operator =(const X& p);





И как раз в тему о multiple dispatching

Дело в том, что семантика присваивания полиморфна по отношению к двум видам объектов:
что присваивается

чему присваивается

Возможны тут 4 случая

Тип источникаТип приёмникаСемантика операцииBaseBaseНормальное присваивание объекта класса BaseBaseDerivedНедопустимая операция, так как часть членов класса Derived не будет присвоенаDerivedBaseУсечение Derived до Base, опасная, но допустимая в С++ операция, поскольку часть данных теряетсяDerivedDerivedНормальное присваивание объекта класса Derived

Именно поэтому operator= как бы не наследуется и не переопределяется.
Поэтому я бы рассматривал этот конкретный пример совершенно отдельно от обсуждения виртуальных функций, которые достаточно просты по
своей семантике.



автор2. Как часто вы используете виртуальные функции в своих программах и как лично вы относитесь к данному механизму?

Ну, как часто, так часто, как надо. Это зависит от задачи. В общем, полиморфизм на типе объекта используется везде, где используются иерархии классов и операции над этими классами.
С точки зрения семантики виртуальных функций в С++, она, безусловно, контринтуитивна, потому что естественным для программиста было бы, если бы все методы были автоматом виртуальными. Появление в С++ необходимости явно требовать
оформления вызова виртуальной функции как косвенного вызова через таблицу виртуальных методов безусловно связана
с необходимостью обеспечить управление быстродействием результирующей программы, получаемой из исходного кода.
И хотя в общем стоимость виртуального вызова не так уж и сильно больше стоимости вызова обычного (оба на самом деле
достаточно высоки, потому что надо формировать аргументы и переключать стек), во времена появления С++, наверное,
разработчики боялись всего-всего, и я полагаю, что Страустрап просто остерёгся делать все поголовно функции виртуальными.

В более современных языках, которые являются наследниками С++, -- Java и C# -- виртуальные вызовы делаются автоматически
везде.

Кстати, не многие помнят, что слово virtual в английском языке означает "действительный", и именно поэтому это слово используется
в этом случае.

автор3. Считаете ли вы ослабление правил замещения для типа возвращаемого значения и для аргументов правильным решением? Интересно, если бы комитет не принял предложения об этом, каким образом были бы решены возможные проблемы(пример из теории компиляторов, метод clone в базовом и производных классах). Лично мне кажется, что это привело бы к изменениям в системе типов языка, что в конечном счете могло положительно сказаться на ней.

Я не очень понял, о чём ты тут ... Я бы думал, что кардинальное решение этой проблемы -- множественная диспетчеризация.
Другой вариант решения, очень простой -- это использовать вместо
Код: plaintext
1.
void X::copy(const X*src)


функцию
Код: plaintext
1.
X* X::clone() const



Тут семантика меняется, не смотря на то, что в принципе функция делает то же самое, и всё становится сильно легче, потому что полиморфизм идёт только по первому и единственному аргументу.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409139
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)SashaMercury,

Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б"

Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование".
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409418
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivkealon(Ruslan)SashaMercury,

Параллельное наследование насколько мне известно не реализовано ещё ни в одном языке к сожалению. Всё ложится на плечи программиста на уровне "я знаю что класс А всё таки класс Б"

Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование".
нет, именно то, что SashaMercury заметил

в С++ оно не особо критично, так как виртуальнных конструкторов всё равно нема
архитектурно проблема появляется, например, так:
есть контейнер определённых объектов (можно для усложения к этим объектам добавить ссылку на контейнер)

у этого контейнера да и у объектов есть виртуальные методы

в потомке этого контейнера нужно: расширить дочерние объекты новой функциональностью
довольно часто нужно обращаться к новым методам контейнера из объекта и наоборот, а описания у нас имеют базовые типы - пришли к проблеме постоянно каста
kealon(Ruslan)"я знаю что класс А всё таки класс Б"
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409423
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivнет, это не так. можно программировать вообще без виртуальных функций, на шаблонном полиморфизме, на современном С++ еще на лямбдах, и чем новее версия языка, тем более он нас к этому стимулирует.
Ну и гвозди можно микроскопом забивать, но молотком удобнее. А интерфейсы реализовывать удобнее всего с помощью виртуальных функций.
MasterZivВиртуальные функции нужны только когда у вас в программе есть иерархии классов.
Иерархии (помимо реализации интерфейсов) в правильно спроектированной программе не нужны.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409436
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyMasterZivнет, это не так. можно программировать вообще без виртуальных функций, на шаблонном полиморфизме, на современном С++ еще на лямбдах, и чем новее версия языка, тем более он нас к этому стимулирует.
Ну и гвозди можно микроскопом забивать, но молотком удобнее. А интерфейсы реализовывать удобнее всего с помощью виртуальных функций.
MasterZivВиртуальные функции нужны только когда у вас в программе есть иерархии классов.
Иерархии (помимо реализации интерфейсов) в правильно спроектированной программе не нужны.
Это заявление эквивалентно тому, что Duck Typing - необходимая и достаточная на все случаи жизни.

Не согласен, инкапсуляция данных тоже важна.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409447
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)MasterZivпропущено...


Скорее всего, ты и имеешь в виду множественную диспетчеризацию, а не "параллельное наследование".
нет, именно то, что SashaMercury заметил

в С++ оно не особо критично, так как виртуальнных конструкторов всё равно нема
архитектурно проблема появляется, например, так:
есть контейнер определённых объектов (можно для усложения к этим объектам добавить ссылку на контейнер)

у этого контейнера да и у объектов есть виртуальные методы

в потомке этого контейнера нужно: расширить дочерние объекты новой функциональностью
довольно часто нужно обращаться к новым методам контейнера из объекта и наоборот, а описания у нас имеют базовые типы - пришли к проблеме постоянно каста
kealon(Ruslan)"я знаю что класс А всё таки класс Б"


нафига тебе контейнер с полиморфными методами?

ну да, иногда нужно что-то настраивать в алгоритмах, но виртуальные методы - не единственный способ это сделать.
C++ - не Ява, тем он и хорош, что можно делать по-разному.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409469
kealon(Ruslan)
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivнафига тебе контейнер с полиморфными методами?

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

но в данном случае это явная недоработка, которая мешает компонентному использованию
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409743
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kealon(Ruslan)MasterZivнафига тебе контейнер с полиморфными методами?

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

но в данном случае это явная недоработка, которая мешает компонентному использованию


и часто ты наследуешься от контейнеров и что-то там переопределяешь?
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409952
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
У меня возник еще один вопрос, и он должен был быть раньше того, что я спрашивал выше.

0. Модель размещения производного объекта в памяти на 1982 год (думаю, что и сейчас не сильно изменилась) заключалась в объединении его собственных членов и членов базового класса.
Anatoly MoskovskySashaMercury,

1) Когда я вижу a.xxx или a->xxx то я ожидаю, что вызовется xxx именно у того класса, на экземпляр которого указывает a (или сам им является). В С++ это так и есть для полей и виртуальных функций. А для обычных функций класса - нет, даже если наследник переопределил функцию.

Вы, судя по всему, говорите об этом
Код: 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.
class A
{
public:
	void print();
};

void A::print()
{
	printf("A\n");
}

class B:public A
{
public:
	void print();
};

void B::print()
{
	printf("B\n");
}

int main()
{
	A a;
	a.print();//A
	B b;
	b.print();//B
	b.A::print();//A
}



Но это скорее агрегация. И если поведение выше кажется логичным, то какое адекватное поведение в 1982 Bjarne мог ожидать от такого?
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
class A
{
public:
	void print();
};

void A::print()
{
	printf("A\n");
}

class B:public A
{
};


int main()
{
	A a;
	a.print();
	B b;
	b.print();
}



И это выглядит так, будто агрегация и наследование перемешаны. Потому, и не только потому, но и в целом, почему BS не сделал все методы виртуальными по умолчанию? Если метод будет переопределен в производном классе, то именно это определение фактически будет использовать для объектов данного класса. В том случае, когда не существует возможность представить реализацию конкретного метода в базовом классе, можно, например, использовать инструкцию аналогичную для чисто виртуальных функций. Если можно, приведите пожалуйста пример, где реализация виртуальных функций в таком формате была бы плохим решением. Наверняка тут есть подводные камни
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409956
Фотография SashaMercury
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И странно, что абстрактные классы не появились сразу, к выходу Cfront 1.0 в 1985. Ведь BS приводит такой пример в 1982, где очевидно, что они нужны (в качестве базового используется класс Shape, виртуальные методы draw(), rotate())
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39409960
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SashaMercuryпочему BS не сделал все методы виртуальными по умолчанию?

Производительность. Вызов виртуального метода это как минимум два лишних обращения к
случайному участку памяти. Кэши процессора не резиновые, а тогда их вообще не было.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410112
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovSashaMercuryпочему BS не сделал все методы виртуальными по умолчанию?

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


Почему ДВА и почему к СЛУЧАЙНОМУ?
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410113
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
MasterZivПочему ДВА
В случае вызова виртуальной функции: чтение указателя vtable (RAM) ->чтение адреса функции (RAM)->выполнение маш. команды call
Вызов обычной функции: выполнение маш. команды call без чтения RAM (адрес функции - внутри команды)
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410119
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly Moskovsky,

Указатель vtable лежит с данными объекта. Так что на кэш не повлияет, если объект нетривиальный, т.е. работает со своими мемберсами.
Так что лишней можно считать одну операцию.

Не стоит также забывать, что оптимизатор может производить невиртуальный вызов виртуальных ф-ций.
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410252
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglТак что лишней можно считать одну операцию.
Считать можно что угодно, но операций там две )))
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410261
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Anatoly MoskovskyСчитать можно что угодно, но операций там две )))
"лишняя" - одна
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410269
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил"лишняя" - одна
Anatoly MoskovskyВ случае вызова виртуальной функции: чтение указателя vtable (RAM) ->чтение адреса функции (RAM)->выполнение маш. команды call
Вызов обычной функции: выполнение маш. команды call без чтения RAM (адрес функции - внутри команды)
...
Рейтинг: 0 / 0
К виртуальным функциям
    #39410550
Фотография CEMb
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dimitry SibiryakovЛично я бы ожидал, что ошибка компиляции возникнет ещё раньше, когда идёт переопределение
метода с другой сигнатурой.по идее, explicit решает эту проблему
MasterZivКстати, я видел в сети предложение в стандарт для реализации в С++ множественной диспетчеризации в виртуальных методах, вот это была бы бомба!А можно подробнее описать, что это?
...
Рейтинг: 0 / 0
25 сообщений из 106, страница 1 из 5
Форумы / C++ [игнор отключен] [закрыт для гостей] / К виртуальным функциям
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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