C++:在运行时找出自定义 class 的类型
C++: Find out type of custom class at runtime
我想创建一个多图,将多个位图映射到它们的特定字符。对于拉丁字符,有更多的位图(因为字体大小)。我还需要存储中文字符。有不同的字体(称为 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,0x24,0x24,0x24,0x24,0x24,0xe4,0x04,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x09,0x08,0x07,0x00,0x00};
BMPData BMPmeg5A{ 0x01, 0x15, 0x05, 0x02 };
BMPData BMPmeg7A{ 0x7E, 0x09, 0x09, 0x09, 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, Bitmap>('A', 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)));
因为当你使用抽象和基 classes 时,你通常总是需要它是一个指向基 class 的 指针,而不是不仅仅是基础 class.
最后,要获得最终名称,您可以简单地使用:
std::cout << "Type of found element: " << pairFound->second->name() << std::endl;
感谢您的帮助。
我稍微更改了 class 定义,因为我认为它可能更优雅
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, uint8_t xDisplacement, uint8_t yDisplacement, uint8_t width, uint8_t height, 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, uint8_t xDisplacement, uint8_t yDisplacement, uint8_t width, uint8_t height, std::vector<int> BMPData)
: MegFamily{ OverallSize, xDisplacement, yDisplacement, width, height, 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,0x24,0x24,0x24,0x24,0x24,0xe4,0x04,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x09,0x08,0x07,0x00,0x00 };
BMPData BMPmeg5A{ 0x01, 0x15, 0x05, 0x02 };
BMPData BMPmeg7A{ 0x7E, 0x09, 0x09, 0x09, 0x7E };
Meg5 meg5_A = Meg5(5, 0, 0, 4, 5, BMPmeg5A);
Meg7 meg7_A = Meg7(6,0,0,5,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)));
现在可以在运行时确定类型。
谢谢!
我想创建一个多图,将多个位图映射到它们的特定字符。对于拉丁字符,有更多的位图(因为字体大小)。我还需要存储中文字符。有不同的字体(称为 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,0x24,0x24,0x24,0x24,0x24,0xe4,0x04,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x09,0x08,0x07,0x00,0x00};
BMPData BMPmeg5A{ 0x01, 0x15, 0x05, 0x02 };
BMPData BMPmeg7A{ 0x7E, 0x09, 0x09, 0x09, 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, Bitmap>('A', 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)));
因为当你使用抽象和基 classes 时,你通常总是需要它是一个指向基 class 的 指针,而不是不仅仅是基础 class.
最后,要获得最终名称,您可以简单地使用:
std::cout << "Type of found element: " << pairFound->second->name() << std::endl;
感谢您的帮助。 我稍微更改了 class 定义,因为我认为它可能更优雅
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, uint8_t xDisplacement, uint8_t yDisplacement, uint8_t width, uint8_t height, 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, uint8_t xDisplacement, uint8_t yDisplacement, uint8_t width, uint8_t height, std::vector<int> BMPData)
: MegFamily{ OverallSize, xDisplacement, yDisplacement, width, height, 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,0x24,0x24,0x24,0x24,0x24,0xe4,0x04,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x09,0x09,0x08,0x07,0x00,0x00 };
BMPData BMPmeg5A{ 0x01, 0x15, 0x05, 0x02 };
BMPData BMPmeg7A{ 0x7E, 0x09, 0x09, 0x09, 0x7E };
Meg5 meg5_A = Meg5(5, 0, 0, 4, 5, BMPmeg5A);
Meg7 meg7_A = Meg7(6,0,0,5,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)));
现在可以在运行时确定类型。 谢谢!