C++ 使用Qt';获取对象实例类名;s元对象系统
我有三门课:C++ 使用Qt';获取对象实例类名;s元对象系统,c++,qt,qt5,qmetaobject,qmetatype,C++,Qt,Qt5,Qmetaobject,Qmetatype,我有三门课: class Being : public QObject { Q_OBJECT public: explicit Being(QObject *parent = nullptr); }; class Animal : public Being { Q_OBJECT public: explicit Animal(QObject *parent = nullptr); }; class Dog : public Animal { Q_OBJ
class Being : public QObject {
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr);
};
class Animal : public Being {
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr);
};
class Dog : public Animal {
Q_OBJECT
public:
explicit Dog(QObject *parent = nullptr);
};
BEIN的实施情况如下:
Being::Being(QObject *parent) : QObject(parent) {
qDebug() << staticMetaObject.className();
}
问题是:有没有办法实现Being的构造函数,这样我就可以访问指向Being基类的实际实例,这样上面代码的日志就会是:
Being
Animal
Dog
?
编辑:
我的目的是希望能够在Being基类中处理Animal.txt
、Being.txt
和Doc.txt
。根据实例的类型,我需要知道是否需要解析Animal.txt
,Being.txt
或Doc.txt
,以获得更多信息
Qt支持这个吗?是否有一种机制可以使用C++/Qt实现这一点?如果没有,是否有任何优雅的折衷解决方案?在
的构造函数中是不可能的,因为封闭对象尚未构造,因此有关它的元数据不可用。但是,您可以编写在对象构造后应调用的初始化
方法,例如,使用打印功能:
class Being : public QObject {
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr) { qDebug() << this->metaObject()->className(); } // this will always print "Being"
void initialize() { qDebug() << this->metaObject()->className(); } // this will print the actual class name
};
class Animal : public Being {
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr) { initialize(); } // you can already use this method in the constructor
};
TEST(xxx, yyy)
{
Being* being = new Being();
Being* animal = new Animal();
being->initialize();
animal->initialize(); // or you can call it later
}
类为:公共QObject{
Q_对象
公众:
显式存在(QObject*parent=nullptr){qDebug()元对象()->className();}//这将始终打印“存在”
void initialize(){qDebug()元对象()->className();}//这将打印实际的类名
};
动物类别:公共存在{
Q_对象
公众:
显式Animal(QObject*parent=nullptr){initialize();}//您已经可以在构造函数中使用此方法
};
测试(xxx,yyy)
{
Being*Being=新的Being();
成为*动物=新动物();
正在->初始化();
animal->initialize();//或者您可以稍后调用它
}
如果initialize
方法不是一个好的解决方案,你可以通过Being
构造函数:explicit Being(QString名称,QObject*parent=nullptr;
然后explicit Animal(QObject*parent=nullptr):Being(“Animal”){}
,但我认为它不够优雅
我的目的是希望能够在Being基类中处理Animal.txt、Being.txt和Doc.txt。我需要知道,根据实例的类型,我是否需要解析Animal.txt、Being.txt或Doc.txt以获得更多信息
永远不要让基类知道它的子类
无论它看起来多么诱人,都不要去做(即使你知道怎么做)
一个类可能有数百个子类。例如QObject
。QObject
(或者可能)是否应该知道重新实现QMainWindow
因此,无论这个设计决策的原因是什么,改变它!
可能的解决方案
如果文本文件的处理算法相同,不管子类是什么,创建一个基类方法来进行处理,并从子类调用它
如果算法依赖于子类,则将方法抽象化,即虚拟
且不进行实现(=0
),并将实现转移到子类。在Being::Being构造函数中是否绝对需要此功能?一旦构造了对象,您可以引用元对象,但此时不可能(封闭对象尚未完全构造)不一定在构造函数中,但我需要一种机制来知道,在我的Being类中,实例的类型是Being
,Animal
或Dog
…如果这是为了调试,那就是元对象->类名()
。如果您计划对类名进行分派,请改用多态性。不,多态性不仅仅用于调试,请参阅我的编辑。我知道这是一种自动机制,可以根据使用的实例类型收集更多信息。
class Being : public QObject {
Q_OBJECT
public:
explicit Being(QObject *parent = nullptr) { qDebug() << this->metaObject()->className(); } // this will always print "Being"
void initialize() { qDebug() << this->metaObject()->className(); } // this will print the actual class name
};
class Animal : public Being {
Q_OBJECT
public:
explicit Animal(QObject *parent = nullptr) { initialize(); } // you can already use this method in the constructor
};
TEST(xxx, yyy)
{
Being* being = new Being();
Being* animal = new Animal();
being->initialize();
animal->initialize(); // or you can call it later
}