Если у меня есть указатель на объект, который происходит из абстрактного базового класса (поэтому я не могу создать новый объект этого класса), и я хочу сделать глубокую копию упомянутый объект, существует ли более сжатый способ выполнения этого, чем для того, чтобы абстрактный базовый класс создал новую чистую виртуальную функцию copy
, которую должен реализовать каждый наследующий класс?Создание копии объекта абстрактного базового класса
ответ
Нет, но метод copy
не должен быть болезненным:
class Derived : public Base
{
public:
Base *copy() const
{
return new Derived(*this);
}
};
(при условии, у вас уже есть конструктор копирования, который, если вам нужно глубокое копирование, вы будете иметь).
Вы хотите, чтобы метод 'copy' был чистым виртуальным в базовом классе, поэтому компилятор скажет вам, не забыли ли вы его предоставить. –
@Mark - это только обеспечивает ложное чувство безопасности, так как любые внуки тоже могли бы забыть. –
@Noah, тоже правда. Но это только одна причина, чтобы избежать внуков, я мог бы предоставить других. –
Предлагаемый «экземпляр», обычно называемый «клон», является обычным подходом. Альтернативой может быть фабрика и отправка с использованием rtti, чтобы найти правильного обработчика, чтобы затем вызвать конструктор копирования на производном типе.
struct Abc
{
virtual void who() const = 0;
};
struct A : Abc
{
virtual void who() const { std::cout << "A" << std::endl;}
};
template<class T>
Abc* clone(Abc* abc)
{
T* t = dynamic_cast<T*>(abc);
if (t == 0)
return 0;
return new T(*t);
}
struct B : Abc
{
virtual void who() const { std::cout << "B" << std::endl;}
};
typedef Abc* (*Cloner)(Abc*);
std::map<std::string, Cloner> clones;
void defineClones()
{
clones[ typeid (A).name() ] = &clone<A>;
clones[ typeid (B).name() ] = &clone<B>;
}
Abc* clone(Abc* abc)
{
Abc* ret = 0;
const char* typeName = typeid(*abc).name();
if (clones.find(typeName) != clones.end())
{
Cloner cloner = clones[typeName];
ret = (*cloner)(abc);
}
return ret;
}
void test()
{
defineClones();
Abc* a = new A;
Abc* anotherA = clone(a);
anotherA->who();
Abc* b = new B;
Abc* anotherB = clone(b);
anotherB->who();
}
В то время как выше работ, сам факт, что использует RTTI будет достаточно, чтобы убедить большинство идти нормальный подход. Однако, это была причина предотвращения изменений в базовом классе, это может быть полезно.
Это эффективный? Предельные затраты на добавление нового типа действительно являются однострочным. Уловка заключается в том, что будет легко забыть добавить эту строку с каждым новым классом. Или вы можете видеть это как потенциал роста, что весь код клонирования живет в одном файле, и нам не нужно менять поддерживаемую иерархию для ее обработки.
Некоторое время назад кто-то в comp.lang.C++ спросил, как автоматически создать функцию clone(). Кто-то еще представил идею, по которой я расширился. Ничего из этого не проверено кодом, и я никогда не пробовал его ... но я думаю, что он работает: http://groups.google.com/group/comp.lang.c++/browse_thread/thread/c01181365d327b2f/9c99f46a8a64242e?hl=en&ie=UTF-8&oe=utf-8&q=comp.lang.c%2B%2B+noah+roberts+clone&pli=1
- 1. NHibernate и создание абстрактного базового класса сущности
- 2. Создание объекта для абстрактного класса
- 3. Создание объекта виртуального базового класса
- 4. Создание объекта абстрактного класса в классе наследования
- 5. Создание объекта базового класса из производного класса
- 6. Python - Тестирование абстрактного базового класса
- 7. Абстрактный подкласс абстрактного базового класса
- 8. Переопределение абстрактного метода базового класса
- 9. Получение типа абстрактного базового класса из класса
- 10. Создание абстрактного базового класса для обработки различных типов перечислений
- 11. Создание абстрактного класса pdo
- 12. Создание глубокой копии объекта
- 13. C++ избежать вызова абстрактного конструктора базового класса
- 14. Создание копии объекта
- 15. C++/CLI - Создание копии объекта
- 16. Вызов конструктора из «абстрактного» базового «класса»
- 17. Оператор постфиксного абстрактного базового класса C++
- 18. Определить, нет ли конструктора абстрактного базового класса?
- 19. Конструкторы и деструкторы абстрактного базового класса защищены?
- 20. Функции C++ для абстрактного базового класса
- 21. TcpClient поле абстрактного базового класса постоянно расположены
- 22. Protobuff.NET - различная сериализация абстрактного базового класса
- 23. Hibernate Аннотация Наследование абстрактного базового класса
- 24. Autofac решить все EventHandlers абстрактного базового класса
- 25. Как переопределить поведение базового абстрактного класса?
- 26. Как инициализировать защищенные члены абстрактного базового класса?
- 27. Получить недостающие члены абстрактного базового класса
- 28. Построение подклассов из базового абстрактного класса
- 29. Создание и добавление объекта из базового класса производного класса массива
- 30. Создание пользовательского абстрактного класса ArrayAdapter
Что дает вам идею, что это неэффективно? – GManNickG
@GMan «неэффективен», как в том, что требует много работы для программиста, по сравнению с, скажем, отличным однострочным трюком или чем-то, что выполнит то же самое (как я иногда обнаруживаю, это случай в Stackoverflow) – wrongusername
Слово вы хотите, чтобы это было «кратким». Вероятно, вам следует уточнить это в своем вопросе. И дайте понять, что вы подразумеваете ремонтопригодность и чистоту, а не производительность. – GManNickG