Re[3]: VC11. Фигня с виртуальными функциями.
От: Erop Россия  
Дата: 25.02.13 16:30
Оценка: 1 (1)
Здравствуйте, Logot, Вы писали:

L>да, но если захочется сделать так:


L>
L>struct Base
L>{
L>    virtual ~Base() {}

L>    std::tr1::shared_ptr<Base> Clone() const { return std::tr1::shared_ptr<Base>(new Base( *this )); }
L>};

L>struct Der : Base
L>{
L>    std::tr1::shared_ptr<Der> Clone() const { return std::tr1::shared_ptr<Der>(new Der( *this )); }
L>}
L>


L>то облом


Расширю свой коммент.
Вот у меня есть код, который только про Base знает:
void process_Base( Base* b )
{
    Base* b1 = b-Clone();
    b1->Method1();
    delete b1;
}
или с RAII там всяким
void process_Base( Base* b )
{
    xxx::unique_ptr<Base> b1 = b-Clone();
    b1->Method1();
}


Как это вообще работает с Der? А просто работает, есть много способов это сделать, но суть в том, что в Der есть реально виртуальная Clone, которая вернёт Base* и NVI версия, которую зовёт виртуальная, и которая возвращает Der*.
Или, наоборот, реальная та, которая виртуальная + NVI пустышка со static_cast внутри...

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

но есть и хорошие новости. Никто не мешает нам сделать всё ручками:
struct Base {
    virtual ~Base() {}
    std::tr1::shared_ptr<Base> Clone() const { return std::tr1::shared_ptr<Base>( doClone() ); }
protected:
    virtual Base* doClone() { return new Base( *this ); }
};

struct Der : Base {
    std::tr1::shared_ptr<Der> Clone() const { return std::tr1::shared_ptr<Der>( doClone() ); }
protected:
    Der* doClone() override { return new Der( *this ); }
};


просто геморно, но можно через обобщение CRTP вывернуться, например:
struct IClonableBase { 
    virtual ~IClonableBase() {}

    template<typename Der>
    std::tr1::shared_ptr<Der> CloneAs() const
        { return toSPtrIfCan<Det>( doClone() ); }
protected:
    virtual IClonableBase* doClone() = 0;
    template<typename To>
    static std::tr1::shared_ptr<To> toSPtrIfCan( IClonableBase* p )
    {
        if( To* asTo = dynamic_cast<To*>( p ) ) {
            return std::tr1::shared_ptr<To>( asTo );
        }
        delete p;
        assert( false );
        return std::tr1::shared_ptr<To>();
    }
};

template<typename TDer, typename TBase = IClonableBase> class Clonable : public TBase {
protected:
    virtual TDer* doClone() const override { return new TDer( *static_cast<TDer*>( this ); }
};

template<typename TDer, typename TBase>
TDer* Clonable<TDer, TBase>::doClone() const { return new TDer( *static_cast<const TDer*>( this ) ); }

template<typename TDer, typename TBase>
std::tr1::shared_ptr<Der> Clonable<TDer, TBase>::Clone() const { return std::tr1::shared_ptr<Der>( doClone() ); }

// Пример:
class Base : public Clonable<Base> {
};

class Der : public Clonable<Der, Base> {
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: VC11. Фигня с виртуальными функциями.
От: Erop Россия  
Дата: 25.02.13 16:32
Оценка:
Здравствуйте, Logot, Вы писали:

E>>Конечно облом. Как ты себе представляешь реализацию такой виртуальности?..


L>Не, ну почему нет?


Ну попробуй на С эту конструкцию "скомпилировать". Как оно по твоему должно работать-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: VC11. Фигня с виртуальными функциями.
От: Erop Россия  
Дата: 25.02.13 16:34
Оценка:
Здравствуйте, Logot, Вы писали:

L>имея

L>
L>typedef base* base_ptr;
L>typedef der* der_ptr;
L>


L>с условием, что везде используются base_ptr или dev_ptr, вместо base* или dev*


L>а потом как-то поменять на

L>
L>typedef std::tr1::shared_ptr<base> base_ptr;
L>typedef std::tr1::shared_ptr<der> der_ptr;
L>


L>очень хотелось бы, чтобы оно собралось в этом случае


То, что при этом случиться клизьма с владением не смущает?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: VC11. Фигня с виртуальными функциями.
От: Logot Украина  
Дата: 25.02.13 19:30
Оценка:
Здравствуйте, Erop, Вы писали:

E>То, что при этом случиться клизьма с владением не смущает?..


В данном случае не смущает, прототип предполагает передачу права владения клона
Re[7]: VC11. Фигня с виртуальными функциями.
От: Erop Россия  
Дата: 25.02.13 20:08
Оценка:
Здравствуйте, Logot, Вы писали:

L>В данном случае не смущает, прототип предполагает передачу права владения клона


Ну как бы в случае указателей надо не забыть сделать delete, а в случае умныхх указателей не забыть не сделать deete...

Как ты себе представляешь автоматическое исправление всех косяков при такой правке?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: VC11. Фигня с виртуальными функциями.
От: Logot Украина  
Дата: 25.02.13 21:27
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Logot, Вы писали:


L>>В данном случае не смущает, прототип предполагает передачу права владения клона


E>Ну как бы в случае указателей надо не забыть сделать delete, а в случае умныхх указателей не забыть не сделать deete...


E>Как ты себе представляешь автоматическое исправление всех косяков при такой правке?


Да никак не представляю, контраргумент принят
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.