Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.72/32: Рейтинг темы: голосов - 32, средняя оценка - 4.72
0 / 0 / 0
Регистрация: 09.01.2012
Сообщений: 7

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

09.01.2012, 15:05. Показов 6817. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день! Вопрос в следующем... Возможно ли создать копию объекта производного класса зная указатель на базовый класс? У меня получился вариант, приведенный ниже. Однако в нем не нравится функция 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);
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.01.2012, 15:05
Ответы с готовыми решениями:

Как создать копию объекта, зная его указатель?
Здравствуйте, существует следующая проблема. В своей программе я рисую график используя класс QwtPolarPlot. По нажатию на график, должно...

Вызов метода производного класса через указатель на базовый класс
Всем привет ! Подскажите почему , при выполнении строки 45 я получаю ошибку ? А именно при выполнении выражения c-&gt;fnz() ...

Ошибка при выполнении оператора присваивания производного класса через указатель на базовый
Здравствуйте, не могу понять из-за чего ошибка. Надо в производном классе объявить оператор сложения и обратится к нему через базовый. ...

4
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
09.01.2012, 15:09
KAlexey, clone можно сделать виртуальным методом класса Base, возвращающим указатель на Base. В каждом классе её надо переопределить так, чтобы она возвращала адрес нужного класса. Или, как вариант, использовать паттерн "Абстрактная фабрика".
0
0 / 0 / 0
Регистрация: 09.01.2012
Сообщений: 7
09.01.2012, 15:44  [ТС]
Спасибо Можно конечно перенести 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)
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
09.01.2012, 15:46
KAlexey, нет, так не получится. С++ - статически типизируемый язык, все типы всех создаваемых объектов должны быть известны на стадии компиляции.
1
0 / 0 / 0
Регистрация: 29.08.2009
Сообщений: 12
08.05.2012, 22:37
Столкнулся с такой же проблемой. Решил вот так:

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, а копия остается нетронутой.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
08.05.2012, 22:37
Помогаю со студенческими работами здесь

Указатель на объект базового класса и адрес объекта производного класса
Пример кода: class Class1 { public: Class1(int x) { j = new int; *j = x; } ~Class1() {delete j;}

Как создать копию объекта на который указывает указатель
У меня есть указатель класс Student, который хранит информацию о студентах(имя, фамилию, телефон) в строках в стиле Си, то есть private...

Как создать копию объекта любого класса?
Set MyObj = AnyObj присваивает MyObj ссылку на объект AnyObj. Как скопировать объект целиком ? (класс содержит слишком много внутренних...

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

Возможно ли указатель производного класса инициализировать объектом базового класса?
имеется связка наследуемых классов A-&gt;B а от B наследуются одновременно еще два класса B-&gt;C и B-&gt;D class A { public: ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru