Здравствуйте, 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> {
};
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Logot, Вы писали:
E>>Конечно облом. Как ты себе представляешь реализацию такой виртуальности?..
L>Не, ну почему нет?
Ну попробуй на С эту конструкцию "скомпилировать". Как оно по твоему должно работать-то?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, 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>очень хотелось бы, чтобы оно собралось в этом случае
То, что при этом случиться клизьма с владением не смущает?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>То, что при этом случиться клизьма с владением не смущает?..
В данном случае не смущает, прототип предполагает передачу права владения клона
Здравствуйте, Logot, Вы писали:
L>В данном случае не смущает, прототип предполагает передачу права владения клона
Ну как бы в случае указателей надо не забыть сделать delete, а в случае умныхх указателей не забыть не сделать deete...
Как ты себе представляешь автоматическое исправление всех косяков при такой правке?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, Logot, Вы писали:
L>>В данном случае не смущает, прототип предполагает передачу права владения клона
E>Ну как бы в случае указателей надо не забыть сделать delete, а в случае умныхх указателей не забыть не сделать deete...
E>Как ты себе представляешь автоматическое исправление всех косяков при такой правке?
Да никак не представляю, контраргумент принят