我有一个代码,其中有一些指向同一基类的派生类的指针。在某一时刻,我需要创建另一个指向此派生类之一的指针,但我不知道在编译时它将指向哪个类。下面是一个代码示例:
#include <iostream>
using namespace std;
class Polygon {
protected:
int width, height;
public:
void set_values (int a, int b)
{ width=a; height=b; };
virtual int area() = 0;
};
class Rectangle: public Polygon {
public:
int area()
{ return width*height; }
};
class Triangle: public Polygon {
public:
int area()
{ return width*height/2; }
};
int main () {
Rectangle* rect = new Rectangle;
Triangle* trgl = new Triangle;
Polygon* ppoly;
trgl->set_values (4,5);
ppoly = trgl;
cout << ppoly->area() << 'n';
trgl->set_values (8,5);
cout << ppoly->area() << 'n';
return 0;
}
如上所述编写代码,"ppoly"指向与trgl相同的内存,因此2行cout << ppoly->area() << 'n'
打印不同的结果,因为我更改了指针trgl
的宽度。在我的代码中我不想要这种行为,但我希望ppoly
是相同类型trgl
的新指针。我尝试使用Polygon* ppoly = new Polygon
,但在编译时返回错误:
错误:抽象类类型"多边形"的新表达式无效
如何更正软件?
你要求的是一个虚拟(复制(构造函数,即一个clone()
函数。
显然,不能只使用与基类相关的构造来实例化派生类。但是基类指针后面仍然有一个派生类实例,它可以封装构造另一个实例的"能力"。
这个成语被称为虚拟构造函数 - 它甚至不难实现。简而言之,您将拥有一个非静态虚拟方法,该方法在堆上构造一个新实例,并且可以从基类中使用。它将看起来像这样:
Polygon* poly = get_a_poly_which_really_is_some_derived_class();
Polygon* another_poly = poly->create();
笔记:
- 我刚刚注意到,使用纯虚拟方法克隆C++类基本上是一个克隆,并且具有相似的答案。
- 除非您真的需要,否则我不建议您这样做。我想除了诉诸虚拟构造对象之外,可能还有更好的选择。
- 不要使用原始指针,而是使用
std::unique_ptr<Polygon>
或std::shared_ptr<Polygon>
。