C++中如何在父类方法内获取调用该方法的子类名称
在C++父类方法中获取调用它的子类类名
方法1:虚函数实现多态返回类名
这是最实用的方案,借助C++多态特性实现。在父类里定义一个纯虚函数用来返回类名,每个子类重写这个函数,返回自己的类名称。父类方法调用这个虚函数时,会自动触发子类的实现,拿到真实的子类类名。
代码示例:
#include <iostream> #include <string> class Base { public: virtual ~Base() = default; // 纯虚函数,子类必须重写 virtual std::string getClassName() const = 0; void printClassName() { // 调用子类的getClassName std::cout << "当前子类类名:" << getClassName() << std::endl; } }; class Derived1 : public Base { public: std::string getClassName() const override { return "Derived1"; } }; class Derived2 : public Base { public: std::string getClassName() const override { return "Derived2"; } }; int main() { Base* d1 = new Derived1(); d1->printClassName(); // 输出:当前子类类名:Derived1 Base* d2 = new Derived2(); d2->printClassName(); // 输出:当前子类类名:Derived2 delete d1; delete d2; return 0; }
方法2:用RTTI(运行时类型信息)
C++的RTTI机制可以通过typeid获取对象的实际类型,但有两个前提:
- 编译时要开启RTTI支持(主流编译器默认开启,比如GCC加
-frtti,MSVC默认就有) - 父类必须至少有一个虚函数(否则
typeid只会识别父类类型,触发不了多态)
代码示例:
#include <iostream> #include <typeinfo> #include <string> class Base { public: virtual ~Base() = default; // 必须有虚函数才能让typeid识别子类类型 void printClassName() { // typeid(*this).name()返回的格式随编译器变化,比如GCC会带长度前缀 std::cout << "当前子类类名:" << typeid(*this).name() << std::endl; } }; class Derived : public Base {}; int main() { Base* d = new Derived(); d->printClassName(); // GCC下可能输出"6Derived",MSVC下输出"Derived" delete d; return 0; }
注意:typeid返回的名称格式不统一,如果需要标准化的类名,建议结合方法1来处理。
方法3:宏定义减少重复代码
如果有大量子类,不想每个都手动写重写函数,可以用宏自动生成返回类名的代码:
#include <iostream> #include <string> class Base { public: virtual ~Base() = default; virtual std::string getClassName() const = 0; void printClassName() { std::cout << "当前子类类名:" << getClassName() << std::endl; } }; // 定义宏,自动生成getClassName的重写函数 #define DEFINE_CLASS_NAME(className) \ std::string getClassName() const override { \ return #className; \ } class DerivedA : public Base { public: DEFINE_CLASS_NAME(DerivedA) }; class DerivedB : public Base { public: DEFINE_CLASS_NAME(DerivedB) }; int main() { Base* a = new DerivedA(); a->printClassName(); // 输出:当前子类类名:DerivedA Base* b = new DerivedB(); b->printClassName(); // 输出:当前子类类名:DerivedB delete a; delete b; return 0; }
内容的提问来源于stack exchange,提问作者Yasasa Jayasuriya
相关产品推荐
相关产品推荐

