|
C++: проблема возвращения значения при полиморфизме | ☑ | ||
---|---|---|---|---|
0
Ненавижу 1С
гуру
28.09.11
✎
11:19
|
Предположим мы хотим реализовать некую фабрику классов, строим абстрактное "ядро":
class AbstractObject { public: virtual void Test() =0 }; class AbstractFactory { public: virtual AbstractObject CreateObject() const =0; //какой тип вернуть? }; и тут же натыкаемся проблему какой тип должен возвращать метод virtual AbstractObject CreateObject() const Варианты: 1. Объект AbstractObject вернуть нельзя, ибо он содержит абстрактный метод Test(), но даже если сделать пустую реализацию {} у него, то полиморфизм теряется 2. Ссылку AbstractObject& вернуть нельзя, ибо в конкретной реализации это будет ссылка на временный объект, что запрещено компилятором 3. Константная ссылка const AbstractObject&. Но тут же накладывается условие на константность методов результата Test() const. Не всегда приемлемо. 4. Единственно приемлемый вариант указатель: AbstractObject*. Минус этого подхода состоит в том, что мы обязаны самостоятельно следить за уничтожением объектов. 5. Альтернативный вариант. Создать обертку class WrapObject { private: AbstractObject* object; public: WrapObject(AbstractObject* obj) { object = obj; } ~WrapObject() { delete object; } void Test() const { object->Test(); } }; Соответственно реализация class AbstractFactory { public: virtual WrapObject CreateObject() const =0; }; Прошу комментировать, возможно я сильно заблуждаюсь |
|||
1
Oftan_Idy
28.09.11
✎
11:24
|
копай в сторону "чисто виртуальных" функций pure virtual func1().
Нужно сделать чисто виртуальный класс |
|||
2
Ненавижу 1С
гуру
28.09.11
✎
11:25
|
(1) какой класс сделать чисто виртуальным?
|
|||
3
dmpl
28.09.11
✎
11:31
|
(0) А что компилятор пишет при попытке вернуть тип объект?
|
|||
4
Ненавижу 1С
гуру
28.09.11
✎
11:37
|
(3) пишет, что нельзя, ибо тип содержит абстрактный метод
если метод сделать неабстрактным, то ошибок нет, но тип "обрезается" и полиморфизма нет |
|||
5
Ненавижу 1С
гуру
28.09.11
✎
11:39
|
все разобрался, я заново "открыл" умные указатели ))
class WrapObject { private: AbstractObject* object; public: WrapObject(AbstractObject* obj) { object = obj; } ~WrapObject() { delete object; } AbstractObject* operator->() { return object; } }; |
|||
6
Кириллка
28.09.11
✎
12:13
|
(6)Иди еще раз переоткрой, а то он у тебя вредный к использованию получился.
|
|||
7
Кириллка
28.09.11
✎
12:18
|
+6 Объяснить нужно почему вредный?
|
|||
8
Ненавижу 1С
гуру
28.09.11
✎
12:20
|
(6) да задача просто несколько другая, если б нужен был бы именно он, то взял бы готовый
|
|||
9
fellow
28.09.11
✎
12:26
|
(4) Для реализации полимормфизма класс не обязан быть абстрактным. Виртуальных функций достаточно.
|
|||
10
Ненавижу 1С
гуру
28.09.11
✎
12:27
|
(9) да, но полиморфизм теряется, если присваивать именно объекты
|
|||
11
fellow
28.09.11
✎
12:28
|
(10)Возвращайся ссылку на объект.
|
|||
12
Ненавижу 1С
гуру
28.09.11
✎
12:30
|
(11) посмотри внимательно (0), там описаны различные варианты и дальнейшее их развитие
|
|||
13
Кириллка
28.09.11
✎
12:38
|
Полиморфизм работает на указателях + виртуальность.
|
|||
14
Ненавижу 1С
гуру
28.09.11
✎
12:40
|
(13) на ссылках оно тоже работает, только ссылки ограниченны, как видим, в использовании
|
|||
15
fellow
28.09.11
✎
12:40
|
virtual void Test() {} решит твою проблему.
|
|||
16
Кириллка
28.09.11
✎
12:43
|
(14)ээ, создание объекта CreateObject в куче и возврат на него константной ссылки??
|
|||
17
Кириллка
28.09.11
✎
12:44
|
+16 ну и в догонку: спорить влом - указатели только.
|
|||
18
Ненавижу 1С
гуру
28.09.11
✎
12:45
|
(15) не решит, я писал почему
(17) здесь да, но надо следит за их уничтожением |
|||
19
Кириллка
28.09.11
✎
12:48
|
(18)всегда указатели для работы полиморфизма.
|
|||
20
fellow
28.09.11
✎
12:51
|
class AbstractObject
{ public: virtual void Test() =0 }; class AbstractFactory { public: virtual AbstractObject& CreateObject() const =0; }; |
|||
21
fellow
28.09.11
✎
12:52
|
+ Возврат ссылки не обязательно означает возврат временного объекта.
|
|||
22
Ненавижу 1С
гуру
28.09.11
✎
12:55
|
(20) ты пробовал это компилировать?
|
|||
23
Кириллка
28.09.11
✎
12:55
|
(21)ты реализацию CreateObject покажи тогда.
|
|||
24
fellow
28.09.11
✎
12:55
|
AbstractObject& RealFactory::CreateObject()const
{ RealObject* probj = new RealObject; return *probj; } |
|||
25
fellow
28.09.11
✎
12:57
|
(22) Да, компилируется. Стандарту С++ соответствует.
|
|||
26
Кириллка
28.09.11
✎
12:58
|
(24)горцев рождаем чтоли? :)
|
|||
27
fellow
28.09.11
✎
12:59
|
(26) Поясни свою мысль.
|
|||
28
Ненавижу 1С
гуру
28.09.11
✎
13:04
|
(27) кто его уничтожит то? пока вижу никто
|
|||
29
fellow
28.09.11
✎
13:06
|
(28) Когда ты вдоволь наиграешься с объектом, вызовешь delete &pRealObj;
|
|||
30
Ненавижу 1С
гуру
28.09.11
✎
13:07
|
(29) спасибо, тогда лучше указатели
|
|||
31
fellow
28.09.11
✎
13:12
|
(30) На самом деле, разница невелика. В любом случае, если твоя фабрика создаёт полиморфные объекты, которые будут использоваться вне функции, вызвавшей фабрику, тебе нужно будет или самому заботиться о времени их жизни, или использовать умные указатели (например, shared_ptr из boost).
|
|||
32
Кириллка
28.09.11
✎
19:26
|
(27)ну мысль уже пояснили и тему раскрыли.
Все-таки полиморфизм, я думаю, ТС подразумевался в таком виде: class A {}; // подразумеваем виртуальный деструктор class B : public A {}; A* a = new B; |
|||
33
fellow
28.09.11
✎
20:11
|
(32) ТС, я думаю, хотел определить обобщённую стратегию создания объектов достаточно произвольного вида и манипулирования ими, для чего ему и понадобились абстрактные классы фабрик и объектов. Поскольку классы абстрактные, то создать объекты этих классов невозможно, им можно только наследовать. Это - часть формального определения системы, создаваемой ТС.
Полиморфизм возникает как естественное следствие различной реализации классов-потомков (реальных фабрик и объектов) при единой спецификации наследуемых интерфейсов базовых (абстрактных в данном случае) классов. При этом, говоря вообще, без виртуальных функций получаем статический полиморфизм. Ссылка обозначает объект, на который она ссылается, а следовательно имеет в этом отношении семантику указателя. Более того, их реализация и представляет собой указатель. А вот кто такие "горцы", которых зачем-то кто-то собирается "рождать", мне не понятно :) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |