Альтернативный метод наследования.№ 1
Феликс

Теоретический вопрос об альтернативе наследованию в объектно-ориентированном программировании. Я предлагаю не наследовать базисный класс, а влючать его в структуру
сабкласса в качестве первого члена и задавать конверции сабкласса в базисный класс и
во все более ранние базисные классы по цепочке.
Я имею в виду деларации в структуре сабкласса (в С++):
<base class name> base;
operator <base class name>() {return *(<base class name> *) this;}

Этот механизм наследования проще стандартного. Какие у него недостатки?
Профиль 

Альтернативный метод наследования.№ 2
yxo

А как быть с полиморфизмом ? То есть, как будет выглядеть в твоей конструкции следующее выражение:

Base *b = new Derived();

Кстати, в твоём примере запускается copy constructor, что не есть гут:

operator <base class name>() {return *(<base class name> *) this;}

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

Альтернативный метод наследования.№ 3
Феликс

С++ не конвертирует пойнтеры различных типов автоматически, даже если сами типы конвертируются. Этот недостаток можно обойти следующим образом:

Base *b = (Base *) new Derived();

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

Альтернативный метод наследования.№ 4
Феликс

Спасибо за замечание, что вызывается copy constructor. Я пока не знаю, как это можно избежать.
Профиль 

Альтернативный метод наследования.№ 5
yxo


С++ не конвертирует пойнтеры различных типов автоматически, даже если сами типы конвертируются. Этот недостаток можно обойти следующим образом:

Base *b = (Base *) new Derived();
Не совсем понял, что имеется в виду. Стандарт С++ поддерживает down-casting, поэтому выражение:

Base *b = (Base *) new Derived();

и:

Base *b = (Base *) new Derived();

абсолютно идентичны.

Зато мой метод избавляет программиста от связанных с наследованием правил
Каких ?
..а также от ошибок, связанных с непреднамеренным использованием переменных
Эти переменные, если они public или protected, предназначены для изменений. Все остальные переменные класса должны быть обьявленны как private и защищены API-ем базового класса. По определению, наследующий класс имеет право менять всё, что он наследует как public или protected. Исходя из этого, задачей создателя базового класса является правильная защита от неконтролируемого доступа.

Несколько вопросов по твоему предложению:

1. Каким образом имплементируется наследование от нескольких базовых классов, часть из которых полно-абстрактные (т.е. не имеет имплементации, как например интерфейсы в Java) ?
2. Каким образом виртуальный метод в наследуемом классе вызывает тот же метод базового класса ? Не происходит ли в этом случае лишний casting поинтера this в тип базового класса ?

Рекомендую почитать про Smalltalk. Очень красивый язык


 ...и днем и ночью учёный всё ходит по цепи кругом...
Профиль 

Альтернативный метод наследования.№ 6
Феликс

Не совсем понял, что имеется в виду.


Если Derived класс "наследует" Base класс по моему методу, то он не наследует его в смысле С++, поэтому выражение Base *b = new Derived(); даёт ошибку компиляции, а выражение Base *b = (Base *) new Derived(); не даёт ошибку.

Каких (правил) ?


С наследованием связаны правила overriding and hiding методов и переменных базисных
классов, а также правила исполнения конструкторов и деструкторов.
Кстати, я бы сделал конструкторы и деструкторы обычными методами void initialize(...)
и void finalize(), и ввёл бы глобальные конструкторы <class name> _<class name>(...),
которые создавали бы объект и вызывали соответствующий initialize(...) метод.
Программист может в initialize(...) методе вызвать base.initialize(...), а не зависеть от каких то правил.

Все остальные переменные класса должны быть обьявленны как private и защищены API-ем базового класса.


Если программист хочет вызвать какой-то метод, то не надо ему это запрещать, по крайней мере не в целях защиты от ошибок, от которых мой метод защищает автоматически. Я предлагаю использовать "//private:" как комментарий в программе и в документации методов.

1. Каким образом имплементируется наследование от нескольких базовых классов, часть из которых полно-абстрактные (т.е. не имеет имплементации, как например интерфейсы в Java) ?


Наследование нескольких классов можно осуществить, включая их в структуру сабкласса, аналогично случаю, когда наследуется один класс. Вызов виртуальных методов использует
таблицу виртуальных методов. Для простоты будем считать, что наследуется только один класс. Пусть каждый класс содержит static type info area c информацией о классе, и пусть любой instance класса содержит пойнтер на type info area. Для любого класса X, занумеруем виртуальные методы начиная от самого низкого базисного класса вверх по цепочке до самого класса X, и поместим pointer to array of pointers to implementations of virtual methods в type info area. Поскольку любому классу известны номера его виртуальных методов, то механизм их вызова очевиден.

2. Каким образом виртуальный метод в наследуемом классе вызывает тот же метод базового класса ? Не происходит ли в этом случае лишний casting поинтера this в тип базового класса ?


Объявление метода virtual означает, что при его вызове будет исполняться метод наивысшего сабкласса. Для того, чтобы вызвать тот же метод базового класса, casting не
поможет. Для этого нужно создать instance базового класса. Но это редко когда нужно.

Профиль 

Альтернативный метод наследования.№ 7
Феликс

Я вижу, что перемудрил с оператором конверсии.
Можно проще:

<base class name> base;
operator <base class name>() {return base;}

В этом случае и copy constructor не вызывается.
Профиль 

Альтернативный метод наследования.№ 8
Феликс

В таком виде это не будет работать, потому что нужно не только конвертировать сабкласс в базисный класс, но и наоборот. Это можно осуществить, если оперировать не с самими классами, а со ссылками на них (references). Ссылка это класс, содержащий pointer на структуру класса. Перед структурой класса помещаем pointer на type info area.
Рассмотрим следующий code:

<base class name> x;
<subclass name> y;

x=y;
y=x;

Переменные x и y содержат ссылки на классы <base class name>_ и <subclass name>_,
которые содержат структуры классов. После исполнения инструкции x=y, х содержит ссылку на объект типа <subclass name>_. При исполнении инструкции y=x, проверяется действительно ли x указывает на структуру типа <subclass name>_. В данном случае это так, а если бы это было не так, то исполнение инструкции y=x вызвало бы сообщение об ошибке.



Профиль 


Вы не зарегистрированы либо не вошли в портал!!!
Регистрация или вход в портал - в главном меню.



 Просмотров:   007691    Постингов:   000008