如何从C++对象中获取类名?

juzqafwq  于 2023-01-28  发布在  其他
关注(0)|答案(9)|浏览(445)

是否也可以获得对象名称?

#include<cstdio>

class one {
public:
    int no_of_students;
    one() { no_of_students = 0; }
    void new_admission() { no_of_students++; }
};

int main() {
    one A;
    for(int i = 0; i < 99; i++) {
        A.new_admission();
    }
    cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
        <<A.no_of_students<<" students";
}

在那里我可以找到名字,比如

[classname] = A.classname() = one
[objectname] = A.objectname() = A

C++是否提供了实现此功能的机制?

epggiuax

epggiuax1#

你可以用预处理器显示变量的名字。

#include <iostream>
#define quote(x) #x
class one {};
int main(){
    one A;
    std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
    return 0;
}

产出

3one    A

#将标记更改为字符串,在预处理该行后,

std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";

当然,如果你做一些

void foo(one B){
    std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
    one A;
    foo(A);
    return 0;
}

你会得到

3one B

因为编译器不会跟踪所有变量的名称。
就像gcc中发生的那样,typeid(). name()的结果是被破坏的类名,要获得demangled version使用

#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
    one<int,one<double, int> > A;
    int status;
    char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
    std::cout<<demangled<<"\t"<< quote(A) <<"\n";
    free(demangled);
    return 0;
}

这给了我

one<int, one<double, int> > A

其他编译器可能使用不同的命名方案。

sulc1iza

sulc1iza2#

使用typeid(class).name
//假定所有包含/命名空间等的说明性代码

#include <iostream>
#include <typeinfo>
using namespace std;

struct A{};
int main(){
   cout << typeid(A).name();
}

重要的是要记住,这给了一个实现定义的名称。
据我所知,没有办法在运行时可靠地获得对象的名称,例如代码中的"A"。
编辑2:

#include <typeinfo>
#include <iostream>
#include <map>
using namespace std; 

struct A{
};
struct B{
};

map<const type_info*, string> m;

int main(){
    m[&typeid(A)] = "A";         // Registration here
    m[&typeid(B)] = "B";         // Registration here

    A a;
    cout << m[&typeid(a)];
}
rxztt3cl

rxztt3cl3#

要获得类名而不损坏内容,可以在构造函数中使用func宏:

class MyClass {
    const char* name;
    MyClass() {
        name = __func__;
    }
}
tez616oj

tez616oj4#

是否希望[类名]为“一”,[对象名]为“A”?
如果是这样的话,这是不可能的。这些名称只是程序员的抽象,实际上并没有在生成的二进制代码中使用。你可以给予类一个静态变量classname,你可以将它设置为'one',和一个普通变量objectname,你可以通过一个方法或构造函数直接赋值。然后你可以查询这些方法以获得类和对象的名称。

iyzzxitl

iyzzxitl5#

只需编写简单的模板:

template<typename T>
const char* getClassName(T) {
  return typeid(T).name();
}

struct A {} a;

void main() {
   std::cout << getClassName(a);
}
r1zhe5dt

r1zhe5dt6#

您可以尝试使用"typeid"
这对“对象”名不起作用,但是你知道对象名,所以你只需要把它存储在某个地方。编译器不关心你给对象起什么名字。
不过,值得记住的是,typeid的输出是编译器特有的,所以即使它在当前平台上产生了你想要的结果,在另一个平台上也可能没有,这对你来说可能是个问题,也可能不是。
另一种解决方案是创建某种类型的模板 Package 器来存储类名,然后需要使用部分专门化来让它为您返回正确的类名,这有编译时工作的优势,但明显更加复杂。
编辑:更加明确

template< typename Type > class ClassName
{
public:
    static std::string name()
    {
        return "Unknown";
    }
};

然后,对于每个类,类似于以下内容:

template<> class ClassName<MyClass>
{
public:
    static std::string name()
    {
        return "MyClass";
    }
};

它甚至可以是宏,如下所示:

#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
    static std::string name() \
    { \
        return #className; \
    } \
}; \

允许你,简单地,做

DefineClassName( MyClass );

最后,要获取类名,您需要执行以下操作:

ClassName< MyClass >::name();

Edit2:更详细地说,您需要将这个“DefineClassName”宏放在您创建的每个类中,并定义一个调用静态模板函数的“classname”函数。
Edit3:想一想......早上第一件事显然是不好的发布,因为你还不如定义一个成员函数“classname()”如下:

std::string classname()
{
     return "MyClass";
}

可按如下方式进行宏处理:

DefineClassName( className ) \
std::string classname()  \
{ \
     return #className; \
}

然后你就可以

DefineClassName( MyClass );

按照您定义的那样添加到类中。

vddsk6oq

vddsk6oq7#

你可以试试这个:

template<typename T>
inline const char* getTypeName() {
  return typeid(T).name();
}

#define DEFINE_TYPE_NAME(type, type_name)  \
  template<>                               \
  inline const char* getTypeName<type>() { \
    return type_name;                      \
  }

DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions

就像这样称呼它:

void main() {
 std::cout << getTypeName<int>();
}
bwntbbo3

bwntbbo38#

@Chubsdad回答的改进,

//main.cpp

using namespace std;

int main(){
A a;
a.run();
}

//A.h
class A{
public:
 A(){};
 void run();
}

//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
   cout << (string)typeid(this).name();
}

将打印:

class A*
hjqgdpho

hjqgdpho9#

下面是获取所创建类的名称的技巧:

struct NameTest {
    NameTest() : mName {std::source_location::current().function_name()} {
    }
    void operator()() {
        auto src_loc = std::source_location::current();

        std::cout << "Class name:\t" << mName  //
                  << "\nFunc:\t\t" << src_loc.function_name() //
                  << "\nLine:\t\t" << src_loc.line() << '\n';
    }
    const std::string mName;
};

int main() {
    NameTest name_test;
    name_test();
    return 0;
}

输出:

Class name: NameTest::NameTest()

Func:       void NameTest::operator()()

Line:       81

一个小的字符串操作将剥离不需要的部分

相关问题