如果不在纯虚拟基类中创建显式函数,就无法完成复制构造吗?
题
我的目标是对一个类进行深度复制,但虚拟类造成了麻烦。
#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’
我计划有更多的 Handler 类(如 Handler1、Handler2 等),它们继承自 Vir,并将拥有自己独特的成员(如 float a;或双 b;ETC)。因此,将所有 Handler 类的所有 getter 和 setter 函数保留在 Vir 类中对我来说是没有意义的。我想将 getter 和 setter 方法保留在 Handler 类中,因为这些成员对于 Handler 类来说是唯一的。编译器不允许我这样做。帮助?
解决方案
也许我错过了一些东西,但如果你使用虚拟的不是更好吗? clone
方法上 Vir
?这意味着您可以避免在 ControlPanel
您自己的答案中概述了复制构造函数。这与 @Andrew Aylett 在中建议的相同 他的回答 和 duplicate
被用来代替 clone
.
就像是
class Vir
{
public:
virtual Vir* clone() const = 0;
...
};
这是在实施 Handler
成为
Handler* Handler::clone() const
{
return new Handler( *this );
}
请注意协变返回类型的使用,即 Handler::clone
被允许返回一个 Handler*
而不仅仅是一个 Vir*
并且仍然是有效的覆盖 Vir::clone
.
这使得 ControlPanel
简单地复制构造函数
ControlPanel( const ControlPanel& c )
: v( c.v->clone() )
{
}
其他提示
添加duplicate()
函数到您的抽象的类,它(在每个派生类)创建与右值并返回它的新实例。另外,考虑copyFrom(Abs other)
功能,保证你从正确的类型,如果是,拷贝复制领域哪些检查。
在一般情况下,如果你的ControlPanel控制类必须的ABS对象的引用,它不应该试图通过检查混凝土Handler对象做其复制,它应该是使复制关该对象的虚拟函数。
更改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 */