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++ 不是这些语言之一。

于 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

编译后的代码中不存在变量名。

但是,您可以使用 some#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();
}

你会期待什么?“一个”每次?那么c/d呢?

于 2009-11-25T10:24:18.717 回答
8

变量名不能在编译后继续存在。您可以做的最好的事情是将变量名称传递给对象构造函数并使用宏将其存储在对象中。后者将导致非常丑陋的代码,因此您只希望将其作为最后的手段。

于 2009-11-25T09:58:53.710 回答
8

赏金:这是我创造的最大和最恶心的黑客之一,但在我看来它足以用于调试原因

#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

语言本身是不可能的。但是,您可以使用预处理器来获取它。但这并不清楚,如果你的类有不同的构造函数,你必须小心。你也必须在每节课上做。

我将 Steven Keith 的示例与#define预处理器结合使用:

#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

我是编程新手,但是在学习了类结构之后,我相信您可能正在寻找的是关键字this。如下例所示(取自 cplusplus.com),您可以看到它类需要引用自身的任何地方使用。

因此,构造函数也可以这样做。

// example on this
#include <iostream>
using namespace std;

class Dummy {
  public:
    bool isitme (Dummy& param);
};

bool Dummy::isitme (Dummy& param)
{
  if (&param == this) return true;
  else return false;
}

int main () {
  Dummy a;
  Dummy* b = &a;
  if ( b->isitme(a) )
    cout << "yes, &a is b\n";
  return 0;
}

http://www.cplusplus.com/doc/tutorial/templates/

于 2015-08-26T08:56:19.883 回答
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

就 C++ 而言,调试符号不存在。因此,没有 C++ 机制允许您对它们做任何事情。是否有可能创建可行的特定于平台的解决方案?可能的。必须分析内存中进程的映像,根据特定格式对其进行解析,找出调试符号(和帧)并将它们映射到地址。本质上,调试本身。值得麻烦吗?在我看来不是。

于 2015-08-21T19:56:44.567 回答
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 回答