数组中对象的C ++多态性 [英] C++ polymorphism of a object in an array

查看:79
本文介绍了数组中对象的C ++多态性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一位嵌入式软件工程师,来自bits和C领域. 在那个世界中,用C中的const表示的闪存中有数据.而RAM中有数据. RAM昂贵且有限,而闪存便宜且足够.此外,由于碎片问题或安全法规的限制,不允许使用new,delete,malloc等进行动态内存分配,因此首选静态设计.

I'm an embedded software engineer and coming from the world of bits and C. In that world, there are data in flash memory represented by const in C. And there are data in RAM. RAMs are expensive and limited, while flash memory is cheap and enough. Also, dynamic memory allocation using new, delete, malloc etc is not allowed due to fragmentation problem or safety regulations, static designs are preferred.

我大约有2000个对象,这些对象具有相似的常量属性但行为不同. 因此,对于他们来说,我将Shape Class定义为一个基类,该基类包含对象的共享属性.为了表示不同的行为,Shape Class具有一种称为Print()的抽象方法,该方法将被父级覆盖.

I've around 2000 objects which have similar constant properties but different behaviors. So for them, I defined Shape Class as a base class which holds shared properties of my objects. And to represent different behavior, Shape Class has one abstract method called Print() which will be overwritten by parents.

ShapeList是重要的部分.这是一个由"const Shapes"组成的const数组,以便它们可以通过链接器放置到闪存部分中.

ShapeList is the important part. It is a const array consists of "const Shapes" so that they will be placed into flash memory section by linker.

下面的程序产生一个输出:

Below program produces an output:

I'm a Shape has 3 dots
I'm a Shape has 4 dots
I'm a Shape has 5 dots

预期输出为:

I'm a Triangle has 3 dots
I'm a Rectangle has 4 dots
I'm a Pentagon has 5 dots

我需要多态行为.当我打印三角形时,它的行为应类似于三角形,而不是形状.我该怎么办?

I need polymorphic behavior. When I print Triangle, it should behave like a Triangle, not as a Shape. How can I do this?

谢谢.

#include <array>
#include <cstdio>
class Shape
{
    public:
    const int DotCount;
    Shape(const int dot): DotCount(dot) {}
    virtual void Print(void) const; // this is virtual method
};

void Shape::Print(void) const
{
    printf("I'm a Shape has %d dots\n", DotCount);
}

class Triangle: public Shape
{
    public:
    Triangle(void): Shape(3) { }
    void Print(void) const;
};

void Triangle::Print(void) const
{
    printf("I'm a Triangle has %d dots\n", DotCount);
}

class Rectangle: public Shape
{
    public:
    Rectangle(void): Shape(4) { }
    void Print(void) const;
};

void Rectangle::Print(void) const
{
    printf("I'm a Rectangle has %d dots\n", DotCount);
}

class Pentagon: public Shape
{
    public:
    Pentagon(void): Shape(5) { }
    void Print(void) const;
};

void Pentagon::Print(void) const
{
    printf("I'm a Pentagon has %d dots\n", DotCount);
}

const std::array<const Shape, 3> ShapeList = { Triangle(), Rectangle(), Pentagon() };

int main(void)
{
    ShapeList.at(0).Print();
    ShapeList.at(1).Print();
    ShapeList.at(2).Print();
    return(0);
}

更多问题: 今天,我意识到虚拟功能还有另一个问题.当我将任何虚函数添加到基类中时,编译器将开始忽略"const"指令,并将对象自动放置到RAM中而不是闪存中.我不知道为什么我已经向IAR提出了这个问题.到目前为止,我得出的结论是,即使使用堆:/

More problem: Today I realized that there is another problem with virtual functions. When I add any virtual functions into base class, compiler start ignoring "const" directive and place object automatically to the RAM instead of flash memory. I don't know why. I've asked this question to IAR. The conclusion I got so far is that Polymorphic behavior is not possible with ROMable classes even with heap :/

推荐答案

正如其他人所指出的那样,便捷而通用的方式并非如此.对其进行修复将导致代码与目标平台的限制不一致.但是,您可以通过几种不同的方式来模拟多态性.

As others have pointed out, the convenient and common way doesn't work like that. Fixing it results in code which is at odds with the restrictions of your target platform. You can, however, emulate polymorphism differently in several different ways.

您可以按以下类型隔离对象:

You can segregate the objects by type like this:

const Triangle tris[] = {tri1, tri2, ...};
const Rectangle rects[] = {rect1, rect2, ...};
// for correct order, if needed
const Shape * const shapes[] = {&tris[0], &rects[2], &rects[0], ...}:

您仍然需要使所有方法(不同类型的行为方式不同)virtual,并且为每个对象支付一个额外的指针(如果计算vtable指针,则为两个). 您还可以删除所有virtual,以使用显式标签:

You still need to make all methods (that behave differently for the various types) virtual, and you pay an extra pointer (two if you count the vtable pointer, which would be a bit unfair) per object. You could also remove everything virtual in favor of an explicit tag:

enum ShapeKind { Triangle, Rectangle, Pentagon };
struct Shape {
    ShapeKind kind;
    int sides;
    ...
};

如果各个子类需要非常不同的成员数据,请使用union. 这有很多严格的限制,导致代码很丑陋,但效果很好.例如,您需要预先了解层次结构,并且子类的大小必须大致相同.请注意,这不一定比virtual替代方法快,但是在适用时,它可以占用更少的空间(一个字节而不是一个vtable指针)和

Use a union if the various subclasses need very different member data. This has numerous severe restrictions and leads to rather ugly code, but can work well. For example, you need know your hierarchy up front and the subclasses need to be roughly the same size. Note that this is not necessarily faster than the virtual alternative, but when it's applicable it can take less space (a byte instead of a vtable pointer) and make introspection leaner.

这篇关于数组中对象的C ++多态性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆