オブジェクト名も取得できますか?
#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++はこれを実現するメカニズムを提供しますか?
プリプロセッサを使用して、変数の名前を表示できます。例えば
#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 use
#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
他のコンパイラは異なる命名スキームを使用する場合があります。
typeid(class).name
を使用します
//すべてのinclude/namespaceなどを想定したイラストコード
#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)];
}
内容をマングリングせずにクラス名を取得するには、コンストラクタでfuncマクロを使用できます。
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
[classname]を 'one'にし、[objectname]を 'A'にしますか?
その場合、これは不可能です。これらの名前はプログラマーの抽象概念にすぎず、生成されるバイナリコードでは実際には使用されません。クラスに「1」に設定した静的変数classnameと、メソッドまたはコンストラクターを介して直接割り当てる通常の変数objectnameを指定できます。その後、これらのメソッドに対してクラス名とオブジェクト名を照会できます。
単純なテンプレートを書くだけです:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
"typeid" を使用してみてください。
これは「オブジェクト」名では機能しませんが、オブジェクト名はわかっているので、どこかに保存する必要があります。コンパイラは、オブジェクトの名前を気にしません。
ただし、typeidの出力はコンパイラ固有のものであるため、現在のプラットフォームで目的のものが生成されても、他のプラットフォームでは生成されない可能性があることに留意してください。これはあなたにとって問題かもしれませんし、そうでないかもしれません。
もう1つの解決策は、クラス名を格納する何らかの種類のテンプレートラッパーを作成することです。その後、部分的な特殊化を使用して、適切なクラス名を返すようにする必要があります。これには、コンパイル時間が機能するという利点がありますが、かなり複雑です。
編集:より明確にする
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 );
あなたがそれを定義するようにクラスに...
@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*