Copy Copy Construction можно сделать без создания явной функции в чистом виде виртуального базового класса?

StackOverflow https://stackoverflow.com/questions/3813964

Вопрос

Моя цель состоит в том, чтобы сделать глубокую копию класса, но виртуальный класс вызывает проблемы.

#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  */
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top