是否有可能获得对象名称?
#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";
}
Run Code Online (Sandbox Code Playgroud)
在哪里我可以取名字,像
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Run Code Online (Sandbox Code Playgroud)
C++是否提供了实现此目的的任何机制?
Sco*_*les 72
您可以使用预处理器显示变量的名称.例如
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出
3one A
Run Code Online (Sandbox Code Playgroud)
在我的机器上.该#
更改的标记成一个字符串,预处理线后
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Run Code Online (Sandbox Code Playgroud)
当然,如果你做的事情
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你会得到
3one B
Run Code Online (Sandbox Code Playgroud)
因为编译器不跟踪所有变量的名称.
正如在gcc中发生的那样,typeid().name()的结果是受损的类名,以获得demangled版本的使用
#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;
}
Run Code Online (Sandbox Code Playgroud)
这给了我
one<int, one<double, int> > A
Run Code Online (Sandbox Code Playgroud)
其他编译器可能使用不同的命名方案.
Chu*_*dad 18
使用 typeid(class).name
//插图代码假设所有包含/命名空间等
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
Run Code Online (Sandbox Code Playgroud)
重要的是要记住,这给出了一个实现定义的名称.
据我所知,没有办法在运行时可靠地获取对象的名称,例如代码中的"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)];
}
Run Code Online (Sandbox Code Playgroud)
gru*_*nge 10
要获取没有修改内容的类名,可以在构造函数中使用func宏:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Run Code Online (Sandbox Code Playgroud)
你想[classname]是'one'而[objectname]是'A'吗?
如果是这样,这是不可能的.这些名称只是程序员的抽象,实际上并不用于生成的二进制代码.您可以为类提供一个静态变量classname,您可以将其设置为"one",也可以通过方法或构造函数直接赋值的普通变量objectname.然后,您可以查询这些方法以获取类和对象名称.
只需编写简单的模板:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
Run Code Online (Sandbox Code Playgroud)
您可以尝试使用"typeid"。
这不适用于“对象”名称,但您知道对象名称,因此您只需要将其存储在某处。Compiler 不关心您命名对象的名称。
不过,值得记住的是,typeid 的输出是编译器特定的东西,所以即使它在当前平台上产生你所追求的东西,它也可能不会在另一个平台上产生。这对您来说可能是也可能不是问题。
另一种解决方案是创建某种模板包装器来存储类名。然后你需要使用部分特化来让它为你返回正确的类名。这具有工作编译时间的优点,但要复杂得多。
编辑:更明确
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Run Code Online (Sandbox Code Playgroud)
然后对于每个类的东西如下:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Run Code Online (Sandbox Code Playgroud)
甚至可以是宏如下:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Run Code Online (Sandbox Code Playgroud)
让你,简单地,做
DefineClassName( MyClass );
Run Code Online (Sandbox Code Playgroud)
最后要获取类名,您将执行以下操作:
ClassName< MyClass >::name();
Run Code Online (Sandbox Code Playgroud)
Edit2:进一步详细说明,您需要将这个“DefineClassName”宏放在您创建的每个类中,并定义一个调用静态模板函数的“类名”函数。
Edit3:考虑一下......早上第一件事显然很糟糕,因为你不妨定义一个成员函数“classname()”,如下所示:
std::string classname()
{
return "MyClass";
}
Run Code Online (Sandbox Code Playgroud)
可以按如下方式进行宏处理:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地放下
DefineClassName( MyClass );
Run Code Online (Sandbox Code Playgroud)
在你定义它的时候进入类......
归档时间: |
|
查看次数: |
144754 次 |
最近记录: |