Copy Copy Construction можно сделать без создания явной функции в чистом виде виртуального базового класса?
Вопрос
Моя цель состоит в том, чтобы сделать глубокую копию класса, но виртуальный класс вызывает проблемы.
#include<iostream>
using namespace std;
class Vir//pure virtual class
{
public:
virtual void hi()=0;
};
class Handler:public Vir
{
public:
int i;
Handler() {}
Handler(int val):i(val) {}
void hi() {cout<<"Value of i="<<i<<endl;}
int getI() const {return i;}
void setI(int j) {i=j;}
};
class ControlPanel
{
public:
Vir *v;
ControlPanel(const ControlPanel& c)//copy constructor
{
v=new Handler;
v->setI(c.getI());
}
int getI()const {return v->getI();}
void initialize() {v=new Handler(10);}
void hi() {v->hi();}
ControlPanel() {}
~ControlPanel() {delete v;}
};
int main()
{
ControlPanel cc;
cc.initialize();
cc.hi();
ControlPanel bb(cc);//copying cc into bb
}
Сообщение об ошибке компиляции:
test.cpp: In copy constructor ‘ControlPanel::ControlPanel(const ControlPanel&)’:
test.cpp:28: error: ‘class Vir’ has no member named ‘setI’
test.cpp: In member function ‘int ControlPanel::getI() const’:
test.cpp:30: error: ‘class Vir’ has no member named ‘getI’
Я планирую иметь множество классов обработчиков (например, Handler1, Handler2 и т. Д.), который наследует от вир и будет иметь свои уникальные члены (например, Float A; или Double B; etc). Поэтому для меня не имеет смысла поддерживать все функции Getter & Setter всех классов обработчиков в классе Vir. Я хочу сохранить свои методы Getter и Setter в классах обработчика, потому что члены уникальны для классов обработчика. Компилятор не позволяет мне это сделать. Помощь?
Решение
Может быть, я что-то не хватает, но ты не был бы лучше с виртуальным clone
метод включения Vir
? Это означает, что вы можете избежать неприятности в ControlPanel
Скопируйте конструктор, изложенные в вашем собственном ответе. Это то же самое, что @ Andrew Aylett предлагает в его ответ с участием duplicate
используется вместо clone
.
Что-то типа
class Vir
{
public:
virtual Vir* clone() const = 0;
...
};
который реализован в Handler
быть
Handler* Handler::clone() const
{
return new Handler( *this );
}
Обратите внимание на использование ковариантного возврата типа IE Handler::clone
разрешено вернуть Handler*
а не просто Vir*
и все же быть действительным переопределением Vir::clone
.
Это делает ControlPanel
Скопируйте конструктор просто
ControlPanel( const ControlPanel& c )
: v( c.v->clone() )
{
}
Другие советы
Добавить duplicate()
Функция для вашего абстрактного класса, который (в каждом полученном классе) создает новый экземпляр с правильными значениями и возвращает его. В качестве альтернативы, рассмотрите copyFrom(Abs other)
Функция, которая проверяет, чтобы убедиться, что вы копируете из правильного типа, и если это так, копирует поля.
В целом, если ваш класс ControlPanel имеет ссылку на объект ABS, не следует пытаться выполнить свое дублирование, проверив объект бетона обработчика, его следует отключить дублирование в виртуальную функцию на этом объекте.
Почему компилятор позволит вам? Эти методы не находятся на этом интерфейсе.
Вы могли бы использовать Заводская модель создать ваше Vir
, чтобы избежать необходимости добавлять все конструкторы Vir
Интерфейс интерфейса. Вы также должны рассмотреть вопрос Рай. Чтобы избежать инициализации функций стиля.
Изменять Vir *v
к Handler *v;
и посмотрите, могут ли ваш код компилировать или нет.
Твой класс Vir
не объявляет / определить setI()
а также getI()
Функции членов.
Или определить Vir
так как
class Vir//pure virtual class
{
public:
virtual void hi()=0;
virtual int getI()const =0;
virtual void setI(int)=0;
};
Вы должны определить getI
а также setI
как (чистый) виртуальный в Vir
сделать их доступными через подклассы. Нет об этом.
Как предложил Стив, я отвечаю на свой вопрос, потому что друг дал мне решение. Надеюсь, что это будет поможет всем, кто возникнет вопрос о том, как сделать глубокую копию в C ++, где виртуальный класс может быть контрольным блоком. Надеюсь, кто-то найдет это полезное.
#include<iostream>
using namespace std;
class Vir//pure virtual class
{
public:
virtual void hi()=0;
virtual int getI() {std::cout << "Inside Base class" << std::endl;}
virtual void setI(int i) {cout<<"In base"<<endl;}
virtual int getX() {}
virtual void setX(int x) {}
};
class Model
{
public:
int x;
Model(const Model& mm) {x=mm.x;}
Model():x(555) {cout<<"Model constructor called"<<endl;}
int getX() {return x;}
void setX(int xx) {x=xx;}
};
class Handler:public Vir
{
public:
int i;
Model *m;
Handler() {m=new Model;cout<<"Handler constructor called"<<endl;}
Handler(const Handler& h)
{
std::cout << "Inside Handler @lineNumber:" << __LINE__ << std::endl;
i=h.i;
m=new Model(*h.m);
}
Handler(int val):i(val) {}
~Handler() {delete m;}
void hi() {cout<<"Value of i="<<i<<endl;}
int getI() {return i;}
void setI(int j) {i=j;}
int getX() {return m->getX();}
void setX(int xx) {m->setX(xx);}
};
class ControlPanel
{
public:
int abc;
Vir *v;
ControlPanel(const ControlPanel& c)//copy constructor
{
std::cout << "Inside ControlPanel @lineNumber:" << __LINE__ << std::endl;
v=new Handler((Handler&)*(c.v));
}
void initialize() {v=new Handler();v->setI(10);abc=222;}
void hi() {v->hi();}
ControlPanel() {}
~ControlPanel() {delete v;}
};
int main()
{
ControlPanel cc;
cc.initialize();
cc.hi();
cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
cout<<"x value cc="<<(cc.v)->getX()<<endl;
ControlPanel bb(cc);//copying cc into bb
cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
cout<<"x value bb="<<(bb.v)->getX()<<endl;
(cc.v)->setI(999);
(cc.v)->setX(888888888);
cout << "(cc.v)->i::" << (cc.v)->getI() << endl;
cout << "(bb.v)->i::" << (bb.v)->getI() << endl;
cout<<"x value cc="<<(cc.v)->getX()<<endl;
cout<<"x value bb="<<(bb.v)->getX()<<endl;
}//main
/*
Output:
Model constructor called
Handler constructor called
Value of i=10
(cc.v)->i::10
x value cc=555
Inside ControlPanel @lineNumber:52
Inside Handler @lineNumber:32
(bb.v)->i::10
x value bb=555
(cc.v)->i::999
(bb.v)->i::10
x value cc=888888888
x value bb=555 */