Как имея указатель на класс A хранящий адрес на объект класса B создать новый объект класса B?
class A {
public:
A() {cout << "A" << endl;}
A(const A& a) {cout << "const A&" << endl;}
virtual ~A() {cout << "~A" << endl;}
};
class B : public A {
public:
B() { cout << "B" << endl; }
B(const B& a) { cout << "const B&" << endl;}
~B() { cout << "~B" << endl;}
};
template<typename T>
void create(const T& link)
{
cout << typeid(link).name() << endl;
T* obj = new T(link);
cout << typeid(*obj).name() << endl;
}
void main(){
A* b=new B;
create(*b);
}
В данном примере typeid(link).name() вернет class B, но созданный объект будет класса A
Предусмотреть это самостоятельно еще на стадии проектирования классов, т.е. завести в свой иерархии классов виртуальный метод clone()
class A {
public:
A() {cout << "A" << endl;}
A(const A& a) {cout << "const A&" << endl;}
virtual ~A() {cout << "~A" << endl;}
virtual A* clone() const { return new A(*this); }
};
class B : public A {
public:
B() { cout << "B" << endl; }
B(const B& a) { cout << "const B&" << endl;}
~B() { cout << "~B" << endl;}
virtual B* clone() const { return new B(*this); }
};
int main()
{
A *b = new B;
A *another_b = b->clone();
...
}
Разумеется, конкретный тип получающегося в результате объекта - параметр времени выполнения, который не может быть "зафиксирован" на стадии компиляции. Распознать этот тип никакие шаблоны вам помочь не смогут. Если вы "точно знаете", что исходный и клонированный объект имеет тип B
(как в данном примере), то приводить указатели к типу B *
придется вручную при помощи downcast-ов.
Можно и с шаблонами, но будет чуть сложнее:
using namespace std;
struct Base
{
Base() { cout << "Base c-tor" << endl; }
virtual void foo() { cout << "Base::foo" << endl; }
virtual ~Base() {}
};
struct D1 : public Base
{
D1() : Base() { cout << "D1 c-tor" << endl; }
virtual void foo() override { cout << "D1::foo" << endl; }
};
struct D2 : public Base
{
D2() : Base() { cout << "D2 c-tor" << endl; }
D2(const D2&) : Base() { cout << "D2 copy c-tor" << endl; }
virtual void foo() override { cout << "D2::foo" << endl; }
};
struct DD : public D1
{
DD() : D1() { cout << "DD c-tor" << endl; }
virtual void foo() override { cout << "DD::foo" << endl; }
};
template <class T> Base* create()
{
return new T;
}
template <class T> Base* copy(const Base* arg)
{
const T* t = dynamic_cast<const T*>(arg);
if (t)
return new T(*t);
else
return new T(); // Здесь Вам решать что делать: бросать исключение, возвращать 0 ил что-то еще
}
int main()
{
Base* b1 = create<DD>();
b1->foo();
Base* b2 = create<D2>();
b2->foo();
Base* b3 = create<Base>();
b3->foo();
cout << "=================" << endl;
Base *b4 = copy<D2>(b1); // неудача *b1 - не экземпляр D2
b4->foo();
Base *b5 = copy<D2>(b2);
b5->foo();
return 0;
}
Вывод:
Base c-tor
D1 c-tor
DD c-tor
DD::foo
Base c-tor
D2 c-tor
D2::foo
Base c-tor
Base::foo
=================
Base c-tor
D2 c-tor
D2::foo
Base c-tor
D2 copy c-tor
D2::foo
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Здравствуйте, я пытаюсь произвести запись информации в текстовый файл и в вектор, далее отсортировать вектор , и попросить вводить информацию...
Доброго времени суток гуру С++ и не толькоНачал изучать этот замечательный язык по книге 2016 , но, как оказывается, некоторые примеры не совсем...
Когда один из клиентов чата закрывает чат(закрывает приложение) на сервере начинает лагать его последнее сообщение(отправляться много раз)...
Делаю небольшой мессенджер (протокол TCP)Есть сервер и клиент