C ++: exact type of contained objects without throws

I got a classic example of a form hierarchy ...

struct Shape { // abstract type
    Shape (int x, int y);

    int x;
    int y;
};

struct Rectangle : public Shape {
    Rectangle (int x, int y, int w, int h);

    int w;
    int h;
};

struct Circle : public Shape {
    Circle (int x, int y, int r);

    int r;
};

Shapes container filled with rectangles and circles

std::list<Shape*> container;

and print functions (in my case, these are collision detection functions)

void print_types (Shape&, Shape&) {
    std::cout << "Shape, Shape" << std::endl;
}

void print_types (Rectangle&, Rectangle&) {
    std::cout << "Rectangle, Rectangle" << std::endl;
}

void print_types (Rectangle&, Circle&) {
    ...

Of course, when I do this:

std::list<Shape*> it;
Rectangle r (0, 0, 32, 32);

for (it = container.begin(); it != container.end(); it++)
     print_types(r, **it);

I do not want to print only the lines "Shape, Shape". I know virtual methods, dynamic_casts and visitors. But is there any elegant way to get out of this without these solutions and preserve my external functions?

+3
source share
4 answers

You should probably stick with virtual functions and only have one print_types function

void print_types(Shape&)

Then add the virtual PrintName function to the base class and override it in the derived class.

.

+7

- , . , (AFAIK) .

, , @Peter ( ).

+4

, , dynamic_cast , virtual, virtual char* name(), Shape .

, .

0

:

- , , . , , , ( ) .

++ , , ; . "Shape, Shape". , . * , , .

I really am not a supporter of this; you can see how it gets out of hand with only two forms, imagine how ugly it is when you add more! However, it shows how to do what you tried to do in C ++.

void print_types (Rectangle*, Rectangle*) {
    std::cout << "Rectangle, Rectangle" << std::endl;
}

void print_types (Rectangle*, Circle*) {
    ... 

void print_types (Rectangle* left, Shape* right) {
    Rectangle* rightRect = dynamic_cast<Rectangle*>(right);
    if (rightRect != NULL) {
        print_types(left, rightRect);
        return;
    }
    Circle* rightCirc = dynamic_cast<Circle*>(right);
    if (rightCirc != NULL) {
        print_types(left, rightCirc);
        return;
    }
    throw /* something to indicate invalid shape */;
}

void print_types (Circle* left, Shape* right) {
    ...

void print_types (Shape* left, Shape* right) {
    Rectangle* leftRect = dynamic_cast<Rectangle*>(left);
    if (leftRect != NULL) {
        print_types(leftRect, right);
        return;
    }
    Circle* leftCirc = dynamic_cast<Circle*>(left);
    if (leftCirc != NULL) {
        print_types(leftCirc, right);
        return;
    }
    throw /* something to indicate invalid shape */;
}
0
source

All Articles