在基类中打印派生类名 [英] Printing derived class name in base class

查看:155
本文介绍了在基类中打印派生类名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何从基类中打印出派生类名称,而不必将构造函数一直向下。换句话说,是否有可能从基类中严格执行这些操作而不在每个派生类中添加代码?



这是我获得的一个示例,如果有一个方法我想摆脱的构造函数链。



编辑:
理想情况下,我正在寻找的东西,基类而不必编辑所有派生类。目前我的实际代码已经得到〜17类(需要更多),所以可以直接从基类做的工作将是理想的。即使它是编译器特定的(g ++或clang)。

  #include< iostream> 

class Base {
public:
Base(std :: string id){
std :: cout<<Creating<< id< < std :: endl;
}
};

class Child:Base {
public:
Child(std :: string id):Base(id){}
Child this).name()){}
};

class GrandChild:Child {
public:
GrandChild(std :: string id):Child(id){}
GrandChild():Child this).name()){}
};

class GrandGrandChild:GrandChild {
public:
GrandGrandChild(std :: string id):GrandChild(id){}
GrandGrandChild this).name()){}
};



int main(){
GrandGrandChild * A = new GrandGrandChild();
GrandChild * B = new GrandChild();
Child * C = new Child();

return 0;
}

打印:

 创建GrandGrandChild 
创建GrandChild
创建子


$ b b

但是编译后添加了前缀。

解决方案


问题是构造多态对象是非常复杂的,在你构建子 c 类,你正在构建一个 Base ,而不是 Child code>


$ b

因此,所有的方法检索动态信息(称为RTTI或RunTime类型信息)被自动锁定以防止此类错误。



出于对称的原因,在析构函数中。






现在,只有构造函数和析构函数被锁定,在所有其他情况下,将会愉快地返回实例的动态类型的 true 名称的 c $ c> name()方法:

  class Base {
public:
std :: string name()const {return typeid(* this).name(); }
};

它会工作...除非你从一个构造函数或析构函数调用它,



现在,对于奇异输出,每个实现(编译器)都允许在这里提供自己的输出(并且他们甚至不需要不同类型,疯狂的呃!)。您似乎正在使用gcc或clang。



demanglers 来解释这样的输出,或者如果你的程序足够简单,你,你可能只是试图手动解析它来删除cruft。类的名称应该完全出现,它将在前面加上一些废话(基本上是命名空间和数字)。


How can I print out the derived class name from the base class without chaining constructors all the way down. In other words is it possible to do this strictly from the base class without adding code in each derived class?

This is an example of what I got, and if there's a way I'd like to get rid of the constructor chaining.

EDIT: Ideally I am looking for something to add into the base class without having to edit all derived classes. At the moment my real code has got ~17 classes(with need for more), so something that could do the job straight from the base class would be ideal. Even if it's compiler specific (g++ or clang).

#include <iostream>

class Base {
public:
    Base(std::string id) {
            std::cout<<"Creating "<<id<<std::endl;
    }
};

class Child : Base {
public:
    Child(std::string id) : Base(id) {}
    Child() : Base(typeid(this).name()) {}
};

class GrandChild : Child {
public:
    GrandChild(std::string id) : Child(id) {}
    GrandChild() : Child(typeid(this).name()) {}
};

class GrandGrandChild : GrandChild {
public:
    GrandGrandChild(std::string id) : GrandChild(id) {}
    GrandGrandChild() : GrandChild(typeid(this).name()) {}
};



int main() {
    GrandGrandChild *A = new GrandGrandChild();
    GrandChild *B = new GrandChild();
    Child *C = new Child();

    return 0;
}

Which prints:

Creating GrandGrandChild
Creating GrandChild
Creating Child

But with compiled added prefix.

解决方案

There is unfortunately no easy solution.

The problem is that constructing polymorphic objects is quite complicated, at the moment you are building the Base subpart of a Child class, you are building a Base still, not a Child (because trying to access Child members would be non-sensical, they have not been built yet!)

As such, all the ways to retrieve dynamic information (known as RTTI or RunTime Type Information) are voluntarily locked down to prevent such mistake.

For symmetrical reasons, the same occur in the destructor.


Now, only the constructor and destructor are so locked down, therefore you can perfectly have a name() method that will happily return the true name of the dynamic type of the instance in all other cases:

class Base {
public:
    std::string name() const { return typeid(*this).name(); }
};

It will work... unless you invoke it from a constructor or destructor in which case it will report the static type.

Now, as far as the "bizarre" output, each implementation (compiler) is allowed to provide its own output here (and they need not even be different for different types, crazy eh!). You seem to be using gcc or clang.

There are demanglers to interpret such output, or if your program is simple enough and their interface scares you, you might simply try to parse it manually to remove the cruft. The name of the class should appear fully, it'll just be preceded with some nonsense (namespaces and numbers essentially).

这篇关于在基类中打印派生类名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆