Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / К виртуальным функциям / 25 сообщений из 106, страница 1 из 5
21.02.2017, 22:40
    #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
21.02.2017, 23:00
    #39408808
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
К виртуальным функциям
SashaMercury,

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

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

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

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

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

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

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

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

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

Кстати, я видел в сети предложение в стандарт для реализации в С++ множественной диспетчеризации в виртуальных методах, вот это была бы бомба!
...
Рейтинг: 0 / 0
22.02.2017, 13:27
    #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
22.02.2017, 13:49
    #39409139
MasterZiv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
К виртуальным функциям
kealon(Ruslan)SashaMercury,

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

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

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


и часто ты наследуешься от контейнеров и что-то там переопределяешь?
...
Рейтинг: 0 / 0
24.02.2017, 15:43
    #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
24.02.2017, 15:53
    #39409956
SashaMercury
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
К виртуальным функциям
И странно, что абстрактные классы не появились сразу, к выходу Cfront 1.0 в 1985. Ведь BS приводит такой пример в 1982, где очевидно, что они нужны (в качестве базового используется класс Shape, виртуальные методы draw(), rotate())
...
Рейтинг: 0 / 0
24.02.2017, 16:26
    #39409960
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
К виртуальным функциям
SashaMercuryпочему BS не сделал все методы виртуальными по умолчанию?

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

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


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

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

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


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