微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++:在运行时找出自定义类的类型

如何解决C++:在运行时找出自定义类的类型

我想创建一个多图,将多个位图映射到它们的特定字符。对于拉丁字符,有更多位图(因为字体大小)。我还需要存储中文字符。有不同的字体(称为 meg5、meg7、_china01)。 meg-family 字体用于拉丁字母,china01 用于中文字母。我需要能够在语言之间切换。这就是为什么我想将它们全部存储在一个 multima 中。对于拉丁字母,我需要确定正确的字体(在 meg5 和 meg7 之间)。 这是我的课程:

class Bitmap {
public:
    virtual ~Bitmap() = default;
    inline std::vector<int> getBMPData() const { return m_data; }
    inline void setBMPData(std::vector<int> data) { m_data = data; }
private:
    std::vector<int> m_data;
};

class MegFamily : public Bitmap {
private:
    uint8_t m_OverallSize = 0;
    uint8_t m_xdisplacement = 0;
    uint8_t m_ydisplacement = 0;
    uint8_t m_width = 0;
    uint8_t m_height = 0;
public:
    MegFamily() {};
    inline uint8_t getoverallSize() const { return m_OverallSize; }
    inline uint8_t getXdisplacement() const { return m_xdisplacement; }
    inline uint8_t getYdisplacement() const { return m_ydisplacement; }
    inline uint8_t getWidth() const { return m_width; }
    inline uint8_t getHeight() const { return m_height; }

    //only for test purposes
    inline void setoverallSize(uint8_t overallSize) { m_OverallSize = overallSize; }
    inline void setXdisplacement(uint8_t xdisplacement) { m_xdisplacement = xdisplacement; }
    inline void setYdisplacement(uint8_t ydisplacement) { m_ydisplacement = ydisplacement; }
    inline void setWidth(uint8_t width) { m_width = width; }
    inline void setHeight(uint8_t height) { m_height = height; }
};

class Meg5 : public MegFamily {};
class Meg7 : public MegFamily {};

class ChineseFont : public Bitmap{};

我想使用例如find('A') 用于所有 A 位图,然后确定它们的字体。 这就是我迄今为止所做的。

    typedef std::vector<int> BMPData;
    std::multimap<char,Bitmap> BMPLibrary;

    ChineseFont SomeChineseName;
    Meg5 meg5_A;
    Meg7 meg7_A;



    BMPData BMPSomeChineseName{0x00,0x38,0x27,0x24,0xe4,0x04,0x00,0x01,0x09,0x08,0x07,0x00};

    BMPData BMPmeg5A{ 0x01,0x15,0x05,0x02 };

    BMPData BMPmeg7A{ 0x7E,0x7E };

    SomeChineseName.setBMPData(BMPSomeChineseName);

    meg5_A.setBMPData(BMPmeg5A);
    meg5_A.setoverallSize(5);
    meg5_A.setXdisplacement(0);
    meg5_A.setYdisplacement(0);
    meg5_A.setWidth(4);
    meg5_A.setHeight(5);

    meg7_A.setBMPData(BMPmeg5A);
    meg7_A.setoverallSize(6);
    meg7_A.setXdisplacement(0);
    meg7_A.setYdisplacement(0);
    meg7_A.setWidth(5);
    meg7_A.setHeight(7);

    BMPLibrary.insert(std::pair<char,Bitmap>('A',meg5_A));
    BMPLibrary.insert(std::pair<char,meg7_A));
    BMPLibrary.insert(std::pair<char,Bitmap>('\u2ed8',SomeChineseName));

    std::cout << "searching for As" << std::endl;
    auto pairFound = BMPLibrary.find('A');

    if (pairFound != BMPLibrary.end())
    {
        size_t numPairsInMap = BMPLibrary.count('A');

        for (size_t counter = 0; counter < numPairsInMap; ++counter)
        {
            std::cout << "Type of found element: " << typeid(pairFound->second).name() << std::endl;
        }
    }

我的输出如下:

searching for As
Type of found element: class Bitmap
Type of found element: class Bitmap

我的问题是:是否可以确定结果是 meg5 还是 meg7 的实例? 感谢您的帮助。

解决方法

如果您不介意添加一些辅助函数,我认为您有一个可能的选择:

class Bitmap {
    ...
public:
    virtual std::string name() const = 0;
};

...

class Meg7 : MegFamily {
    ...
public:
    std::string name() const override { return "Meg7"; }
};

然后(就像其他一些评论所建议的那样)您需要更改

    std::multimap<char,Bitmap> BMPLibrary;
    ...
    BMPLibrary.insert(std::pair<char,Bitmap>('A',meg7_A));

    std::multimap<char,std::unqiue_ptr<Bitmap>> BMPLibrary;
    ...
    BMPLibrary.insert(std::pair<char,std::unqiue_ptr<Bitmap>>('A',std::make_unique<Meg7>(std::move(meg7_A))));
    // or you can just use emplace,which is a bit less verbose
    BMPLibrary.emplace('A',std::make_unique<Meg7>(std::move(meg7_A)));

因为当您使用抽象类和基类时,您通常总是需要它作为指向基类的指针,而不仅仅是基类。

最后,要获得最终名称,您可以简单地使用:

            std::cout << "Type of found element: " << pairFound->second->name() << std::endl;
,

感谢您的帮助。 我稍微改变了类定义,因为我认为它可能更优雅

class Bitmap {
public:
    Bitmap(std::vector<int> BMPData)
        : m_data(BMPData)
    {}
    virtual ~Bitmap() = default;
    inline std::vector<int> getBMPData() const { return m_data; }
    //inline void setBMPData(std::vector<int> data) { m_data = data; }
    void printBMPData() const;
    virtual std::string name() const = 0;
protected:
    std::vector<int> m_data;
};

class MegFamily : public Bitmap {
protected:
    uint8_t m_OverallSize = 0;
    uint8_t m_xDisplacement = 0;
    uint8_t m_yDisplacement = 0;
    uint8_t m_width = 0;
    uint8_t m_height = 0;
public:
    MegFamily(uint8_t OverallSize,uint8_t xDisplacement,uint8_t yDisplacement,uint8_t width,uint8_t height,std::vector<int> BMPData)
        : m_OverallSize(OverallSize),m_xDisplacement(xDisplacement),m_yDisplacement(yDisplacement),m_width(width),m_height(height),Bitmap(BMPData)
    {}
    virtual void hello() const { std::cout << "MegFamily" << std::endl; }
    inline uint8_t getOverallSize() const { return m_OverallSize; }
    inline uint8_t getXDisplacement() const { return m_xDisplacement; }
    inline uint8_t getYDisplacement() const { return m_yDisplacement; }
    inline uint8_t getWidth() const { return m_width; }
    inline uint8_t getHeight() const { return m_height; }
};

class Meg5 : public MegFamily
{
public:
    virtual void hello() const { std::cout << "Meg5" << std::endl; }
    std::string name() const override { return "Meg5"; }
    Meg5(uint8_t OverallSize,std::vector<int> BMPData)
        : MegFamily{ OverallSize,xDisplacement,yDisplacement,width,height,BMPData} {};
    ~Meg5() {};
};
class Meg7 : public MegFamily
{
public:
    virtual void hello() const { std::cout << "Meg7" << std::endl; }
    std::string name() const override { return "Meg7"; }
    Meg7(uint8_t OverallSize,BMPData} {};
    ~Meg7() {};
};

class ChineseFont : public Bitmap
{
public:
    ChineseFont(std::vector<int> BMPData)
        : Bitmap(BMPData) {};
    std::string name() const override { return "ChineseFont"; }
};

另外我实现了你推荐的想法

BMPData BMPSomeChineseName{0x00,0x38,0x27,0x24,0xe4,0x04,0x00,0x01,0x09,0x08,0x07,0x00 };
BMPData BMPmeg5A{ 0x01,0x15,0x05,0x02 };
BMPData BMPmeg7A{ 0x7E,0x7E };


Meg5 meg5_A = Meg5(5,4,5,BMPmeg5A);
Meg7 meg7_A = Meg7(6,7,BMPmeg7A);
ChineseFont SomeChineseName = ChineseFont(BMPSomeChineseName);

std::multimap<char,std::unique_ptr<Bitmap>> BMPLibrary;
    BMPLibrary.emplace('A',std::make_unique<Meg5>(std::move(meg5_A)));
    BMPLibrary.emplace('A',std::make_unique<Meg7>(std::move(meg7_A)));
    BMPLibrary.emplace('\u2ed8',std::make_unique<ChineseFont>(std::move(SomeChineseName)));

现在可以在运行时确定类型。 谢谢!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。