Форум программистов, компьютерный форум CyberForum.ru

Создать копию объекта производного класса зная указатель на базовый - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 17, средняя оценка - 4.88
KAlexey
0 / 0 / 0
Регистрация: 09.01.2012
Сообщений: 7
09.01.2012, 15:05     Создать копию объекта производного класса зная указатель на базовый #1
Добрый день! Вопрос в следующем... Возможно ли создать копию объекта производного класса зная указатель на базовый класс? У меня получился вариант, приведенный ниже. Однако в нем не нравится функция clone которая динамически сравнивает типы с известными ей, и потом вызывает создание нового объекта, копия производного. Минус здесь, всегда приходится знать все типы производных классов от базового. Если появится новый придется делать исправления.
Какие еще возможны здесь варианты? Может есть вариант с использованием шаблонов или еще чего то? Заранее спасибо!

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
 
using namespace std;
 
class Base
{
public:
  Base()
  {
     cout<<"Base constructor default"<<endl;
  };
  
  Base(const Base& obj)
  {
     cout<<"Base constructor copy"<<endl;
  };
  virtual ~Base() {;}
};
 
class Derived1:public Base
{
  public:
  Derived1()
  {
    cout<<"Derived1 constructor default"<<endl;
  }
 
  Derived1(const Derived1& obj)
  {
    cout<<"Derived1 constructor copy"<<endl;;
  }
};
 
class Derived2:public Base
{
  public:
  Derived2()
  {
    cout<<"Derived2 constructor default"<<endl;
  }
 
  Derived2(const Derived2& obj)
  {
    cout<<"Derived2 constructor copy"<<endl;;
  }
};
 
void clone(Base* pBase)
{
  cout<<"clone object"<<endl;
  if (Derived1 *p=dynamic_cast<Derived1*>(pBase)) new Derived1(*p) ;
  if (Derived2 *p=dynamic_cast<Derived2*>(pBase)) new Derived2(*p) ;
}
 
void main()
{
  Derived1 d1;
  Derived2 d2;
  Base* pBase =&d1;
  clone(pBase);
  pBase =&d2;
  clone(pBase);
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.01.2012, 15:05     Создать копию объекта производного класса зная указатель на базовый
Посмотрите здесь:

C++ Использование перегруженного оператора ввода/вывода в поток базового класса для объекта производного класса
C++ Создание объекта произвольного класса по указателю на базовый класс
Указателю на базовый класс присвоить адрес производного класса C++
Задача (разъяснение) в алгоритм (программа, используя базовый и производный классы, создавала массив объектов типа производного класса) C++
C++ Как создать копию объекта, зная его указатель?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.01.2012, 15:09     Создать копию объекта производного класса зная указатель на базовый #2
KAlexey, clone можно сделать виртуальным методом класса Base, возвращающим указатель на Base. В каждом классе её надо переопределить так, чтобы она возвращала адрес нужного класса. Или, как вариант, использовать паттерн "Абстрактная фабрика".
KAlexey
0 / 0 / 0
Регистрация: 09.01.2012
Сообщений: 7
09.01.2012, 15:44  [ТС]     Создать копию объекта производного класса зная указатель на базовый #3
Спасибо Можно конечно перенести clone во внутрь классов, но мой вариант интересует чисто из позновательных целей, на понимание. Представим что в моей реализации мы сделаем Clone шаблонным, чтобы в него попадали различные указатели на разные базовые классы, что то типа

C++
1
2
3
4
5
6
7
8
template <class T>
void clone(T pBase)
{
  cout<<"clone object"<<endl;
  if (Derived1 *p=dynamic_cast<Derived1*>(pBase)) new Derived1(*p) ;
  if (Derived2 *p=dynamic_cast<Derived2*>(pBase)) new Derived2(*p) ;
  ...
}
естественно, что все производные классы я не перечислю, это помоему зло. при этом если вызвать
например typeid(*pBase).name() метод запросто покажет какого типа наш объект. Вот это и смущает
Думал может есть вариант чтото типа на лету динамически определить одной строкой тип объекта и создать его, ну чтото аля new typeid(*T)
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
09.01.2012, 15:46     Создать копию объекта производного класса зная указатель на базовый #4
KAlexey, нет, так не получится. С++ - статически типизируемый язык, все типы всех создаваемых объектов должны быть известны на стадии компиляции.
Ilshat89
0 / 0 / 0
Регистрация: 29.08.2009
Сообщений: 12
08.05.2012, 22:37     Создать копию объекта производного класса зная указатель на базовый #5
Столкнулся с такой же проблемой. Решил вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Base
{
public:
    virtual Base* clone() { return this; }
    virtual ~Base() {}
};
 
class Der1: public Base
{
    char c;
public:
    Der1(): c('m') {}
};
class Der2: public Base
{
    int n;
public:
    Der2(): n(682) {}
};
 
std::vector<Base*> list;
void func(Base *b) {
    Base *ptr = new Base(*b);
    ptr = b->clone();
    list.push_back(ptr);
}
 
int main()
{
    Der1 d;
    Der2 dd;
    func(&d);
    func(&dd);
 
    system("PAUSE");
    return 0;
}
В итоге, в векторе list будут указатели на иниц-ые объекты производных классов. Если что, clone можно переопределить в производных.

Добавлено через 3 часа 21 минуту
Цитата Сообщение от Ilshat89 Посмотреть сообщение
Столкнулся с такой же проблемой. Решил вот так:

C++
1
class Base...
В итоге, в векторе list будут указатели на иниц-ые объекты производных классов. Если что, clone можно переопределить в производных.
Извиняюсь, неправильно написал код, вот верный вариант:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class Base
{
public:
    virtual Base* clone() { return 0; }
    virtual ~Base() {}
};
 
class Der1: public Base
{
    char c;
 
public:
    Der1(): c('m') {}
    
    char& getc() { return c; }
 
    virtual Base* clone() {
        Der1 *p = new Der1;
        p->c = c;
        return p;
    }
};
class Der2: public Base
{
    int n;
public:
    Der2(): n(682) {}
 
    virtual Base* clone() {
        Der2 *p = new Der2;
        p->n = n;
        return p;
    }
};
 
std::vector<Base*> vvv;
void func(Base *b) {
    Base *ptr = b->clone();
    vvv.push_back(ptr);
}
 
int main()
{
    Node n1, n2, n3;
    Manager::ModifyNode(&n2);
    Manager::undoLast();
 
    Der1 d; //d.c = 'm';
    Der2 dd; //dd.n = 546;
    func(&d);
    func(&dd);
    d.getc() = 'a';
 
    system("PAUSE");
    return 0;
}
В первом варианте указатели в списке указывали на переданные объекты d и dd, а также глупо "утекала" память в функции func() В этом коде уже указатели указывают на новые объекты в памяти (копии d и dd). Строка d.getc() = 'a'; изменяет только объект d, а копия остается нетронутой.
Yandex
Объявления
08.05.2012, 22:37     Создать копию объекта производного класса зная указатель на базовый
Ответ Создать тему
Опции темы

Текущее время: 20:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru