Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.12.2010, 15:49   #1
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию convariant return types

добрый день. кто нить разбирался с сабжем? (конвариантный возвращаемый тип).

во всех примерах приводят примерно одинаковый код
Код:
class Base {
public:
    virtual Base* clone() const
    {
        return new Base(*this);
    }
};

class Derived : public Base {
public:
    virtual Base* clone() const
    {
        return new Derived(*this);
    }
};
и хотим вызывать это так
Код:
Derived* d = new Derived;
Derived* d2 = d->clone();
но компиль не дает нам этого сделать, требуя явного преобразования Base * в Derived *. для этого можно поменять возвращаемое значение у замещенной вирт функции

Код:
class Base {
public:
    virtual Base* clone() const
    {
        return new Base(*this);
    }
};

class Derived : public Base {
public:
    virtual Derived * clone() const
    {
        return new Derived(*this);
    }
};
и такой код сработает.

но я не догоняю, для чего это? зачем вообще нужна виртуальная функция с ковариантным типом, если мы хотим создать клон конкретного объекта (а не через указатель на базовый класс). все равно clone мы не сможем использовать через Base* (ибо тип возвращаемого значения виртуальной функции берется из базового класса). если б тип возвращаемого значения брался не из базового, а переопределенного класса я согласен, было бы удобно.

в общем, разъясните мне идиоту.
кой какая инфа есть тут
http://www.lwithers.me.uk/articles/covariant.html
но так же ничего не объяснено, зачем тут виртуал
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 21.12.2010, 16:28   #2
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Я честно говоря прочитал и не смог понять что вас именно волнует так?
Код:
virtual Base* clone() const
    {
        return new Derived(*this);
    }
тут по моему и так ясно, вы возвращаете другой тип, по этому и требует приведение типов. А то, что если есть адрес Base*, но вы знаете что это Derived* на самом деле, то конечно можно сделать такое (Derived*)(Base*)->DerivedField;

Возможно я не понял, но вроде все логично.
BOBAH13 вне форума Ответить с цитированием
Старый 21.12.2010, 16:36   #3
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2BOBAH13
да, возвращается ДРУГОЙ тип и требует приведения типа, если мы хотим это использовать вот так
Код:
Derived* d = new Derived;
Derived* d2 = d->clone();
но авторы статьи не хотят кастовать типы! и предлагают написать так

Код:
class Base {
public:
    virtual Base* clone() const
    {
        return new Base(*this);
    }
};

class Derived : public Base {
public:
    virtual Derived * clone() const
    {
        return new Derived(*this);
    }
};
да, будет работать идеально. мой же вопрос, ЗАЧЕМ clone виртуальна? если для достижения эффекта описанного в статье нужно вызвать объект НЕ ЧЕРЕЗ базовый класс, а напрямую? т.е чем этот код отличается от этого?
Код:
class Base {
public:
    Base* clone() const
    {
        return new Base(*this);
    }
};

class Derived : public Base {
public:
    Derived * clone() const
    {
        return new Derived(*this);
    }
};

    Derived* d = new Derived;
    Derived* d2 = d->clone();
зачем там виртаул?) тип все равно нельзя использовать полиморфно. еслиб можно было написать так

Код:
Base* d = new Derived; // создали derived
Derived* d2 = d->clone(); // тип возвращаемого значения clone берется из Base!!! и опять нужно приведение типа!
ЕСЛИ БЫ это работало (т.е если б тип возвращаемого значения вирт функции брался у derived-a), согласен на 100500%, это удобно. но это не работает
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 21.12.2010, 16:45   #4
BOBAH13
Android Developer
Старожил Подтвердите свой е-майл
 
Аватар для BOBAH13
 
Регистрация: 19.02.2007
Сообщений: 3,708
По умолчанию

Я не уверен, но на то что, у Base и Derived есть один и тот же метод clone, может virtual говорит о том, что Base::clone() не будет доступен т.к. существует теперь Derived::clone(). Но на счет данной теории "зачем?" стоит наверное посмотреть спецификацию C++, а именно virtual, боюсь я не могу ответить на столь специфический вопрос.
BOBAH13 вне форума Ответить с цитированием
Старый 21.12.2010, 16:48   #5
UltimaBeaR
Форумчанин
 
Аватар для UltimaBeaR
 
Регистрация: 21.12.2010
Сообщений: 199
По умолчанию

эм, какбэ в твоем коде (который без виртуал) ты создаешь экземпляр Base когда тебе нужно экземпляр Derived.. а это согласись немного не то что тебе надо

.. вобщем виртуал там для того чтоб ты мог из указателя на base (который на самом деле dreived) вызвать клон и получить derived, другого virtual не делает, если оно тебе ненадо то и не пиши его, меньше объект весить будет

Последний раз редактировалось UltimaBeaR; 21.12.2010 в 16:52.
UltimaBeaR вне форума Ответить с цитированием
Старый 21.12.2010, 16:51   #6
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2BOBAH13
нет, virtual тут говорит как и всегда, что clone замещается в derived. но типы возвращаемого значения всегда берется из Base, поэтому нет возможности использовать clone полиморфно.

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

2UltimaBeaR
ты невнимательно читал. яж описал, что ЕСЛИ БЫ ЭТО РАБОТАЛО (то что ты написал), ЭТО БЫЛО БЫ ОХРЕНЕТИТЕЛЬНОЙ СУПЕРФИЧЕЙ
Цитата:
. вобщем виртуал там для того чтоб ты мог из указателя на base вызвать клон и получить derived
на, вызови

Код:
class Base {
public:
    virtual Base* clone() const
    {
        return new Base(*this);
    }
};

class Derived : public Base {
public:
    virtual Derived * clone() const
    {
        return new Derived(*this);
    }
};

int main()
{
    Base* d = new Derived;
    Derived* d2 = d->clone();
    return 0;
}
типы кастовать нельзя! с кастом и так понятно. и почему это НЕ работает, я тоже написал
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance

Последний раз редактировалось Stilet; 21.12.2010 в 20:41.
pproger вне форума Ответить с цитированием
Старый 21.12.2010, 16:57   #7
UltimaBeaR
Форумчанин
 
Аватар для UltimaBeaR
 
Регистрация: 21.12.2010
Сообщений: 199
По умолчанию

Вобще поидее если ты объявляешь виртуальную функцию с другим заголовком(возвращает другой тип) то эта уже другая виртуальная функция, незнаю будет ли это работать в этом случае, все таки классы из 1ой цепочки наследования, но помоему нет, - зачем так сделали хз
UltimaBeaR вне форума Ответить с цитированием
Старый 21.12.2010, 17:01   #8
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2UltimaBeaR
Цитата:
Вобще поидее если ты объявляешь виртуальную функцию с другим заголовком(возвращает другой тип) то эта уже другая виртуальная функция
ничего подобного. возвращаемый тип не входит в сигнатуру функции. он возьмется из базового класса (если тип полиморфен). а функция перегрузится.
вопрос открыт
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Старый 21.12.2010, 17:14   #9
UltimaBeaR
Форумчанин
 
Аватар для UltimaBeaR
 
Регистрация: 21.12.2010
Сообщений: 199
По умолчанию

дейсвтительно перезаписывается, тогда могу предположить что при полиморфном юзании clone() надо будет в любом случае приводить тип, если же не использовать виртуал то полиморфно юзать вобще не выйдет
UltimaBeaR вне форума Ответить с цитированием
Старый 21.12.2010, 17:19   #10
pproger
C++ hater
СтарожилДжуниор
 
Аватар для pproger
 
Регистрация: 19.07.2009
Сообщений: 3,333
По умолчанию

2UltimaBeaR
возможно. но если бы я хотел приводить тип, я бы не стал менять тип возвращаемого значения с Base* на Derived*, оставил бы Base*, приводил бы тип и этой темы вообще бы не было. а возможность не приводить тип при неполиморфном использовании не очень то и полезна
I invented the term Object-Oriented, and I can tell you I did not have C++ in mind. (c)Alan Kay

My other car is cdr.

Q: Whats the object-oriented way to become wealthy?
A: Inheritance
pproger вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Непонятки с return CodeNOT Общие вопросы C/C++ 2 03.12.2010 23:56
Вопрос по return fs444 Общие вопросы C/C++ 9 20.03.2010 15:07
return и echo dedyshka PHP 5 31.01.2010 16:58
Method must have a return type????? Bobrik Помощь студентам 5 18.05.2009 18:09