16

クラスメソッド内からオブジェクトインスタンス名/変数名を知ることは可能ですか? 例えば:

#include <iostream>

using namespace std;

class Foo {
     public:
          void Print();
};

void Foo::Print() {
     // what should be ????????? below ?
     // cout << "Instance name = " << ?????????;
}

int main() {
    Foo a, b;
    a.Print();
    b.Print();
    return 0;
}
4

13 に答える 13

28

いいえ。変数名はプログラマー向けであり、コンパイラーはアドレスを認識します。

プログラムに関するメタデータ/リフレクションを提供する他の言語がこの機能を提供する可能性がありますが、C++ はそれらの言語の 1 つではありません。

于 2009-11-25T09:53:08.740 に答える
25

言語自体ではありませんが、次のようにコーディングできます。

#include <iostream>
#include <string>

class Foo
{
 public:
    Foo(const std::string& name) { m_name = name;}
    void Print() { std::cout << "Instance name = " << m_name << std::endl; }

  private:
    std::string m_name;
};

int main() 
{
    Foo a("a");
    Foo b("b");

    a.Print();
    b.Print();

    return 0;
}
于 2009-11-25T10:16:09.773 に答える
16

コンパイルされたコードには変数名は存在しません。

ただし、一部を使用#defineして前処理で名前を取得し、コンパイル前に名前を入力することができます。

このようなもの:

#define SHOW(a) std::cout << #a << ": " << (a) << std::endl
// ...
int i = 2;
SHOW (i);
于 2009-11-25T09:54:58.720 に答える
9

それはどういう意味ですか?

void f(T const& p) {
    cout << p.name();
}

T r() {
    T c;
    return c;
}

void g() {
    T a;
    cout << a.name();
    T & b = a;
    cout << b.name();
    T * ptr = &b; 
    cout << ptr->name();

    T d = r();
    cout << d.name();
}

あなたは何を期待しますか?毎回「a」?そして、c / dはどうですか?

于 2009-11-25T10:24:18.717 に答える
8

変数名はコンパイルに耐えられません。最善の方法は、変数名をオブジェクト コンストラクターに渡し、マクロを使用してオブジェクト内に格納することです。後者は非常に醜いコードにつながるため、これは最後の手段としてのみ必要です。

于 2009-11-25T09:58:53.710 に答える
8

報奨金について: これは私が今まで作成した中で最大かつ最も嫌なハックの 1 つですが、私の意見では、デバッグの理由には十分です。

#include <iostream>

#include <typeinfo>
#define DEBUG_INSTANCE( classtype, name ) class _ ## classtype ## _INSTANCE_ ## name ## _  : public classtype \
    { \
        public: \
            _ ## classtype ## _INSTANCE_ ## name ## _ (){ } \
    }; \
_ ## classtype ## _INSTANCE_ ## name ## _ name

class Foo {
public:
    virtual void _MakeTypeIDRunTime() { }
    // A virtual method in the class forces typeid(*this) to be used runtime rather than compiled
    // See: https://stackoverflow.com/a/6747130/1924602

    void Print();
};

void Foo::Print() {
    std::cout << "Instance name = " << typeid(*this).name() << std::endl;
}

int main()
{
    DEBUG_INSTANCE(Foo, a);
    DEBUG_INSTANCE(Foo, b);

    a.Print();
    b.Print();

    system("PAUSE");
    return 0;
}

出力:

Instance name = ?AV_Foo_INSTANCE_a_@?1?main@
Instance name = ?AV_Foo_INSTANCE_b_@?1?main@
Press any key to continue . . .

このマクロは、Foo を継承し、name にインスタンス名を含むクラスを作成します。唯一の制限は、Foo にはデフォルトのコンストラクターがあり、 typeid が継承されたクラスを受け入れて実行時に呼び出されるようにするために、仮想メソッドを含める必要があることです。より良い説明については、https://stackoverflow.com/a/6747130/1924602を参照してください

__VA_ARGS__マクロを使用すると、コンストラクターをサポートできる可能性があります

于 2015-08-22T20:38:56.720 に答える
5

インスタンスがクラスメソッド内からその名前を知ることは確かに可能です:

#include <iostream>

class Foo {
  public:
    void Print() { std::cout << "Instance name = " << this << std::endl; }
};

int main() {
    Foo a, b;
    a.Print();
    b.Print();
    return 0;
}

次のような出力が生成されます。

Instance name = 0x7fff502b8b48
Instance name = 0x7fff502b8b40

変数名を知ることに関しては、確かに不可能です。オブジェクトの存在は、変数の存在を意味するものではありません - このインスタンス:

new Foo();

プロセスの残りの期間は存在しますが、変数に関連付けられることはありません。変数の言語概念は、変数の内容には反映されず、言語変数とオブジェクト間の潜在的な関係は、生成されたコードでのみ表現され、生成されたデータやメタデータでは表現されません。もちろん、すでに指摘したように、言語の一部ではないデバッグ情報へのアクセスを禁止します。

于 2015-08-25T23:13:22.310 に答える
1

言語自体では不可能です。ただし、プリプロセッサを使用して取得できます。しかし、それは明確ではなく、クラスに異なるコンストラクターがある場合は注意する必要があります。また、各クラスで行う必要があります。

#defineSteven Keith の例をプリプロセッサと組み合わせて再利用します。

#include <iostream>
#include <string>

using namespace std;

class Foo
{
 public:
    Foo(const string& name) : m_name(name) {}
    void Print() { cout << "Instance name = " << m_name << endl; }

 private:
    string m_name;
};

#define DRESSED_Foo(var) Foo var(#var)

int main() 
{
    DRESSED_Foo(a);
    DRESSED_Foo(b);

    a.Print();
    b.Print();

    return 0;
}
于 2015-08-23T08:17:34.587 に答える
1
This is not possible "Directly", consider this simple program;

 // stove.cpp 

#include <string.h>
#include <stdio.h>
#include <iostream>

using namespace std;

class Foo {
   char* t;
   size_t length;

     public:
     Foo()
     {
       t = new char(8);
       t = static_cast<char*>(static_cast<void*>(this));

     }
      void Print();
};

    void Foo::Print() {
         // what should be ????????? below ?
          cout << this << " " << strlen (t) << t << endl;
    }

    int main() {
        Foo a;
        a.Print();
        Foo b;
        b.Print();
        return 0;
    }

    you can check the value of t in gdb for both a and b objects,
1) run binary in gdb and put breakpoints on lines where both objects a and b gets created.
2) for both objects a and b , after creation (or in print function, check
print this
print t
    18           }
    (gdb) print this
    $1 = (Foo * const) 0x7fffffffe6e0
    (gdb) print t
    $2 = 0x7fffffffe6e0 "\340\346\377\377\377\177"
    ...
    ...
    ...
    30          Foo b;
    (gdb) s
    Foo::Foo (this=0x7fffffffe6d0) at stov.cpp:15
    15             t = new char(8);
    (gdb) n
    16             t = static_cast<char*>(static_cast<void*>(this));
    (gdb) n
    18           }
    (gdb) print this
    $3 = (Foo * const) 0x7fffffffe6d0
    (gdb) print t
    $4 = 0x7fffffffe6d0 "\320\346\377\377\377\177"
于 2015-08-26T19:37:10.773 に答える
0

それは不可能。C++ には、.NET プラットフォームのような「リフレクション」の概念がありません。しかし、MFC ライブラリには CRunTime クラスがあります。たとえば、ご覧のとおりです。

于 2009-11-25T10:00:56.127 に答える
0

を使用して実行できます#define。クラス内に変数名を保存するマクロを定義します。

#include <iostream>
#include <string>

using namespace std;

#define CREATE_FOO(f) Foo f = Foo(#f);

class Foo {
     public:
          void Print() const;
          Foo(string s): name(s) {};
     protected:
          string name;

};

void Foo::Print() const  {
     cout << "Instance name = " << name;
}


int main() {
    CREATE_FOO(a);
    CREATE_FOO(b);
    a.Print();
    b.Print();
    return 0;
}
于 2015-08-27T08:44:40.170 に答える
0

C++ に関する限り、デバッグ シンボルは存在しません。その結果、C++ メカニズムでは、それらを使用して何かを行うことはできません。機能するプラットフォーム固有のソリューションを作成することは可能でしょうか? 可能。メモリ内のプロセスのイメージを分析し、特定の形式に従って解析し、デバッグ シンボル (およびフレーム) を見つけ出し、それらをアドレスにマップする必要があります。基本的に、それ自体をデバッグします。苦労する価値はありますか?私の意見ではありません。

于 2015-08-21T19:56:44.567 に答える