LINUX.ORG.RU

[c++] абстрактный класс и возвращаемый тип

 


0

0

Добрый день. Вот пытаюсь сделать нечто подобное:

class A { virtual int f() = 0; };

class C { virtual A some() = 0; };

Выдает ошибки типа: test.cpp:6: ошибка: invalid abstract return type for member function ‘virtual AC::some()’

Скажите, почему так нельзя делать?

Объект класса A нельзя создать, потому что у него есть чистая виртуальная функция. Возвращай не объект A, а ссылку или указатель на A.

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

>Возвращай не объект A, а ссылку или указатель на A.

Только смарт-указатель, как наиболее общий вариант. Нефиг плодить интерфейсную вермишель.

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

>>Возвращай не объект A, а ссылку или указатель на A.

>Только смарт-указатель

Все и так знают, что ты ненавидишь Си++

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

> Только смарт-указатель, как наиболее общий вариант.

совсем не факт и возврат ссылки то же имеет полное право на существование.

> Нефиг плодить интерфейсную вермишель.

а именно?

// wbr

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

>> Только смарт-указатель, как наиболее общий вариант.

>совсем не факт и возврат ссылки то же имеет полное право на существование.

А что можно сделать со ссылкой на полиморфный объект которую тебе кто-то вернул? Как например ее можно сохранить в поле своего объекта? Я конечно знаю что я могу сделать поле-ссылку в своем классе и проинициализировать ее в списке инициализации конструктора. Но тогда что будет если хозяин обекта его удалил?

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

> забавно начинается дискуссия:

Это не дискуссия. Судя по вопросу, человек только начал учить Си++, и тут пявляешься ты, весь в белом и с плакатом "Только смарты - труЪ".

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

> А что можно сделать со ссылкой на полиморфный объект которую тебе кто-то вернул?

к примеру вызвать её метод?

class A {
public :
virtual void foo() = 0;
}

std::ostream &operator << (std::ostream &os, const A &a);

class B {
public :
foo &get();
}

B b;
b.get.foo();
std::ostream << "a=" << b.get() << std::endl;

> Как например ее можно сохранить в поле своего объекта? Я конечно знаю что я могу сделать поле-ссылку в своем классе и проинициализировать ее в списке инициализации конструктора.

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

> Но тогда что будет если хозяин обекта его удалил?

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

// wbr

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

> А что можно сделать со ссылкой на полиморфный объект которую тебе кто-то вернул? Как например ее можно сохранить в поле своего объекта?

Можно взять от неё адрес. Можно враппером сохранить. Ссылка это тот же указатель, только без звёздочки и readonly.

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

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

Откуда мне знать, нужно ли клиенту кода сохранять ссылку или не нужно? Я не клиент. А вот если какой-то Цпп-фэн возвращает полиморфный объект по ссылке и не предоставляет возможности клонирования то это да, гиморрой.

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

>> А что можно сделать со ссылкой на полиморфный объект которую тебе кто-то вернул? Как например ее можно сохранить в поле своего объекта?

>Можно взять от неё адрес. Можно враппером сохранить. Ссылка это тот же указатель, только без звёздочки и readonly.

При этом мы не знаем когда этот объект удалят.

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

>> При этом мы не знаем когда этот объект удалят.

>В документации написано :)

Это еще более слабый способ коммуникации между кусками кода нежели "любимый" Строуструпом рефлекшен.

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

Поче му же нельзя? Ведь я не собираюсь возвращать экземпляр A, я собираюсь возвращать экземпляр наследника A, которые будут разными.

К примеру, есть абстрактный класс Number. Есть его наследники IntNumber, DoubleNumber, ComplexNumber и так далее.

А есть класс Formula - его наследники могут быть SqrtFormula, MulFormula и каждый из них имеет ф-цию count(), унаследованную от Formula. И возвращает она Number (а точнее один из его наследников).

Вот задача. Не понимаю как ее на сях решить.

p.s.: делаю это все чтоб "вспомнить" c++, на котором в олимпиадные годы кодил. Про smart-pointer'ы (и даже про smart smart pointer'ы) читал и знал, думаю труда вспомнить не составит если надо.

kost-bebix ★★
() автор топика
Ответ на: комментарий от kost-bebix

> я не собираюсь возвращать экземпляр A

Ты именно это и собираешься сделать.

> делаю это все чтоб "вспомнить" c++, на котором в олимпиадные годы кодил

Афигеть. Лучше начни его учить с нуля.

tailgunner ★★★★★
()
Ответ на: комментарий от kost-bebix

hm.. щас кого то побьют. может быть даже ногами :)

// wbr

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

> Афигеть. Лучше начни его учить с нуля.

Это само собой. Как только в ближайшие дни время появляется - иду за Страуструпом и его друзьями к книжной полке. Но, все же, как сию задачу решить хотел сейчас узнать.

kost-bebix ★★
() автор топика
Ответ на: комментарий от kost-bebix

> как сию задачу решить хотел сейчас узнать.

Я уже сказал - возвращай ссылку или указатель. Absurd сказал - возвращай смартпойнтер. Тебе двух вариантов мало?

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

> > я не собираюсь возвращать экземпляр A > > Ты именно это и собираешься сделать.

Понятное дело что экземпляр D : public A {...} будет считаться тем же A. Тем не менее, у него будут реализованы все виртуальные методы. Поэтому проблем в создании невиртуального класса A не вижу.

kost-bebix ★★
() автор топика
Ответ на: комментарий от tailgunner

> Я уже сказал - возвращай ссылку или указатель. Absurd сказал - возвращай смартпойнтер. Тебе двух вариантов мало?

Эти варианты принял, буду пробовать. Думал может экземпляр все же можно вернуть.

kost-bebix ★★
() автор топика
Ответ на: комментарий от kost-bebix

> Понятное дело что экземпляр D : public A {...} будет считаться тем же A

В данном случае - не будет. Будет сделана попытка создать объект A (вызван конструктор A(A&)), что невозможно. Ты забыл основы языка.

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