Cant Kopie Konstruktion ohne die Schaffung eine explizite Funktion in der reinen virtuellen Basisklasse getan werden?

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

Frage

Mein Ziel ist es, eine tiefe Kopie einer Klasse zu tun, sondern eine virtuelle Klasse verursacht Probleme.

#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
}

Die Kompilation Fehlermeldung:

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’

Ich plane, viel mehr Handler Klassen haben (wie handler1, handler2 etc), die erben von Vir und ihre eigenen einzigartigen Mitglieder haben (wie Schwimmer eine oder Doppel b; usw.). So macht es keinen Sinn für mich alle die Getter & Setter Funktionen aller Handler-Klassen in der Vir Klasse zu halten. Ich möchte, dass meine Getter und Setter-Methoden in den Handler-Klassen halten, weil die Mitglieder einzigartig für die Handler-Klassen sind. Der Compiler ist mir erlaubt, dies nicht zu tun. Hilfe?

War es hilfreich?

Lösung

Vielleicht etwas, was ich bin fehle aber würden Sie nicht besser auf clone mit einer virtuellen Vir Methode sein? Diese Mittel können Sie die fiese Besetzung im ControlPanel Copykonstruktor in Ihrer eigenen Antwort skizzierte vermeiden. Dies ist die gleiche wie @ Andrew Aylett in seine Antwort mit duplicate statt clone verwendet wird.

So etwas wie

class Vir
{
    public:
    virtual Vir* clone() const = 0;
    ...
};

, die in Handler implementiert sein

Handler* Handler::clone() const
{
    return new Handler( *this );
}

Beachten Sie die Verwendung des kovarianten Rückgabetyp heißt Handler::clone erlaubt eine Handler* und nicht nur ein Vir* zurückzukehren und noch eine gültige Überschreibung von Vir::clone sein.

Das macht den ControlPanel Copykonstruktor einfach

ControlPanel( const ControlPanel& c )
    : v( c.v->clone() )
{
}

Andere Tipps

Fügen Sie eine duplicate() Funktion, um Ihre abstrakte Klasse, die (in jeder abgeleiteten Klasse) ist es eine neue Instanz mit den richtigen Werten und kehrt erzeugt. Alternativ sollten Sie eine copyFrom(Abs other) Funktion, die prüft, um sicherzustellen, dass Sie von den richtigen Typ sind kopieren und wenn ja, kopiert die Felder aus.

Im Allgemeinen, wenn Controlpanel-Klasse ein Verweis auf ein ABS-Objekt hat, soll es nicht seine Doppelarbeit zu tun versuchen, durch das konkrete Handler Objekt Inspektion, soll es vorbei sein, um die Vervielfältigung aus zu einer virtuellen Funktion auf dem Objekt.

Warum sollte der Compiler Sie erlauben? Diese Methoden sind nicht auf dieser Schnittstelle.

könnten Sie verwenden den Factory-Pattern Ihre Vir zu erstellen, um zu vermeiden, alle hinzufügen die Konstrukteure zu Vir der Schnittstelle. Sie sollten auch RAII mit initialize () Stil Funktionen zu vermeiden.

Ändern Vir *v zu Handler *v; und sehen, ob Ihr Code kompiliert oder nicht.

Ihre Klasse Vir nicht erklären / setI() und getI() Elementfunktionen definieren.

Oder definieren Vir als

class Vir//pure virtual class
{
    public:
    virtual void hi()=0;
    virtual int getI()const =0;
    virtual void setI(int)=0;
};

Sie haben getI und setI als (rein) virtuell in Vir zu definieren, sie zugänglich über Subklassen zu machen. Kein Weg, um dieses.

Als Steve vorgeschlagen, ich bin der Beantwortung meiner Frage Coz ein Freund gab mir eine Lösung. Hoffe, dass dies eine Hilfe für jedermann sein würde, der die Frage der hat, wie eine tiefe Kopie in C ++ zu tun, wo eine virtuelle Klasse ein Hindernis sein kann. Hoffnung jemand findet das nützlich.

#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  */
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top