可运行的代码示例:在此处在线运行此代码
我确实知道正确的完整示例应该使用模板类,但是为了简单起见,我希望看到一个没有模板的幼稚实现。
我还知道,<或>运算符的虚拟运算符重载在C ++中比多态的compareTo()方法签名更合适。
我也知道数组不是协变的,也不是协变的,我还是想看看这个例子在C ++中应该如何工作,我不想使用像vector这样的STL模板类型
我定义了抽象类(接口):
class Comparable {
public:
virtual int compareTo(Comparable *) = 0;
};
我有一个基类,与“可比”的概念无关
class Shape {
protected:
int width, height;
public:
Shape(int a = 0, int b = 0)
{
width = a;
height = b;
}
virtual int area() = 0;
};
我定义了一个形状后代矩形,它想成为一个可比较的:
class Rectangle : public Shape, public Comparable {
public:
Rectangle(int a = 0, int b = 0) : Shape(a, b) {}
virtual int compareTo(Comparable * other){
return height - dynamic_cast<Rectangle *>(other)->height;
}
int area()
{
return (width * height);
}
};
测试方法和主程序:请参见test(...)方法中的注释。我在这里想念什么?
void test(Comparable* items[]){
// tests polymorphic behavior. For example this would be a sort algorithm,
// which gets and array of comparables (array of pointers to Comparable)
int result = items[0]->compareTo(items[1]);
// result is 42 here, despite it is the meaning of life, is not appropriate. It is the area() method return value of items[0], instead of compareTo()
// Debugging justifies, that not the compareTo method is called on the items[0] instance
// instead the area() method... something is wrong with the cast... and not the correct method address used from the vtable ...
}
int main()
{
Rectangle a(3,14), b(3,11);
Rectangle* rectangles[2];
rectangles[0] = &a;
rectangles[1] = &b;
// This is not good, but what would be the correct?
test((Comparable **)rectangles);
return 0;
}
(Comparable **)rectangles
您得到奇怪的结果,因为此强制转换是无效的reinterpret_cast。此无效的转换导致未定义的行为。在您的情况下,未定义的行为表示自己是在调用其他方法,而不是删除文件,因此很幸运。
C ++数组既不是协变也不是协变,特别是因为这样的强制转换不起作用。相反,您必须使用模板或进行复制:
int main()
{
Rectangle a(3,14), b(3,11);
Rectangle* rectangles[2];
rectangles[0] = &a;
rectangles[1] = &b;
//See these changes here
Comparable* comparables[2];
comparables[0] = static_cast<Comparable*>(rectangles[0]);
comparables[1] = static_cast<Comparable*>(rectangles[1]);
test(comparables);
return 0;
}
在幕后,它可能失败了,因为正常的实现是这样的:
ComparableVirtualTable class layout:
int(*compareTo)(Comparable*);
Comparable class layout:
ComparableVirtualTable* comparableVirtualTable;
ShapeVirtualTable class layout:
int (*area)();
Shape class layout:
ShapeVirtualTable* shapeVirtualTable;
int width;
int height;
Rectangle class layout:
//Contains Shape members
ShapeVirtualTable* shapeVirtualTable;
int width;
int height;
//followed by Comparable members
ComparableVirtualTable* comparableVirtualTable;
值得注意的是:Shape成员和虚拟表位于Comparable虚拟表之前。因此,static_cast<Comparable>*(rectangles[...])
实际上将返回指向的Comparable
部分开始的指针Rectangle
,而不指向其Rectangle
本身的开始。这就是您(Comparable **)
失败的原因,是它将Rectangle
指针数组视为指针数组Comparable
,但是指针没有指向Comparable
数据成员!
旁注:所有带有virtual
方法的类也应virtual
定义一个析构函数:virtual ~Comparable(){}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句