多态函数的 C++ 映射

C++ map of polymorphic functions

我想使用 C++ map 函数来执行一些子例程。 因为,这样的函数映射需要所有映射函数具有相同类型的输入和输出,而我的函数可以有不同的输入类型,我虽然可以让所有这些不同的类型派生自 SuperParentClass

但是,这个想法给我带来了一些麻烦。 它不编译。 实际上,编译器捕获派生类型而不是父类型 class。 但是如果你在我的函数里直接把parentclass,我就不能在我的函数里用到他们的特长了(所以我来求助了)

这是我的 MWE:

#include <functional>
#include <iostream>
#include <map>
#include <string>
#include <math.h> 


class SuperParentClass
{
private:
    /* data */
public:
    std::string nameClass;
};

class ChildClassRectangle : public SuperParentClass
{
private:
    /* data */
public:
    int longueur=2;
    int largeur=2;
};

class ChildClassCircle : public SuperParentClass
{
private:
    /* data */
public:
    int radius=2;
};

int areaRect(ChildClassRectangle rect)
{
    std::cout << "areaRect "<< rect.largeur*rect.longueur << std::endl;
    return 0;
}

int areaCircle(ChildClassCircle circ)
{
    std::cout << "areaCircle "<< 3.14*pow(circ.radius,2) << std::endl;
    return 0;
}


int main()
{  
    std::cout << "TEST " << std::endl;
    std::map<std::string, SuperParentClass> mapObject;
    ChildClassCircle circ;
    circ.radius=2;
    mapObject["Circle"]=circ;
    ChildClassRectangle rect;
    rect.longueur=1;
    rect.largeur=3;
    mapObject["Rectangle"]=rect;
    
    using CallFunc = std::function<int(SuperParentClass)>;
    std::map<std::string, CallFunc> mapFunction;
    // mapFunction["Circle"]=areaCircle;
    // mapFunction["Rectangle"]=areaRect;

    // mapFunction["Circle"](mapObject["Circle"]);
    // mapObject["Rectangle"].largeur=4;
    // mapFunction["Rectangle"](mapObject["Rectangle"]);
};

评论的最后 5 行是我想做的但不起作用。

与其让映射转到函数,不如映射到 SuperParentClass 指针。然后在每个 class 中使用虚函数来封装所需的行为。


int areaRect(ChildClassRectangle rect);
int areaCircle(ChildClassCircle circ);

class SuperParentClass
{
public:
    virtual int area() = 0;
    ... // more code...
};

class ChildClassRectangle : public SuperParentClass
{
public:
    virtual int area() override
    {
        return areaRect(*this);
    }
    ... // more code...
};

class ChildClassCircle : public SuperParentClass
{
public:
    virtual int area() override
    {
        return areaCircle(*this);
    }
    ... // more code...
};

要消除 classes 的值传递,只需将函数移动到 area() 函数中即可。

现在无需单独的映射即可直接调用函数。

这是一个粗略的版本,可能并不完全适用;但传达了这个想法。

void main()
{
    std::map<std::string, SuperParentClass*> mapObject;
    ...
    mapObject["Circle"]=&circ;
    ...
    mapObject["Rectangle"]=&rect;

    ...
    const int circleReturn = mapObject["Circle"]->area();
    // Cannot access derived properties here
    // mapObject["Rectangle"]->largeur=4; // No longer valid.
    const int rectReturn = mapObject["Rectangle"]->area();
}

这里不需要指针;因为物体可以放置在容器上;或一些其他类型的数据结构。这只是为了表明使用虚函数是一种更简单的方法和更好的设计。