Cant Kopie Konstruktion ohne die Schaffung eine explizite Funktion in der reinen virtuellen Basisklasse getan werden?
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?
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 */