【问题标题】:Returning variable name C++返回变量名 C++
【发布时间】:2012-07-06 18:46:30
【问题描述】:

我用这个代码

#define _(x) cout << #x;

作为宏,在程序的开头,返回一个变量名。它在 main 中运行良好,但在嵌套在其他函数中时根本不行。例如,如果定义

void print (int p)
{
   _(p); cout << "=" << p;
}

int main()
{
   int a=1, b=2;
   _(a); 
   cout << " = " << a;
   print(b);
}

输出将是 a = 1 p = 2

有什么办法克服这个问题吗?

【问题讨论】:

  • 但这正是预期的结果。您的第一个变量名为a,第二个变量名为p
  • 为什么? Why> 为什么对变量名感兴趣?
  • 他期望输出为 b=2 但它不起作用,因为他的宏被用来吐出根据他正在操作的范围而变化的变量名。在你的子函数中编译器将变量的名称视为局部范围变量名称,并将在链接到更高级别的范围时连接这些编译符号。我能想到的存储变量名称的唯一方法是从同一范围调用您的宏,然后将其交给类构造函数或其他函数来维护变量。
  • @Wug - 调试器更简单,更有效。
  • 非常糟糕的命名约定:宏名称没有描述其用途;标识符以下划线“_”开头;没有关于宏的用途或用途的 cmets。

标签: c++ macros


【解决方案1】:
#define _(x) cout << #x;
#define print(v) _(v); cout << "=" << v;

它的行为不符合您期望的原因是当您从函数内部调用它时,变量的名称是“p”。所以它完全按照你说的做,即使它不是你的意思。

【讨论】:

  • 如果提问者真的只需要从任何子功能打印,这将起作用。如果是这样的话,倒不是一个坏主意,但是如果提问者有各种各样的事情要从多个子功能中完成,他必须为每个子功能提供一个宏,这也会破坏递归以及使他的可执行文件的大小非常大,具体取决于他需要调用他的函数的次数。
  • 是的,非常感谢。这是我想要的结果,我明白问题出在哪里,可能我表达得不好,但我不知道该怎么做。
  • 我只是在做一些练习来改进 C++。我知道这有点不合时宜。
  • @user1507571 :改进 C++ 的一个好起点是避免宏。 ;-]
【解决方案2】:

这似乎工作正常。 ap 的值分别是 12,这正是您的输出显示的内容。你期待什么输出?

如果您期望第二个输出是 b = 2,那么我认为您对该语言有根本的误解。该函数不知道调用函数在调用它时使用的变量名(如果它完全使用了变量)。具有普遍内省功能的高级语言可能能够做这样的事情,但 C++ 做不到。

也许更重要的是,通过查看代码或在基本调试器中运行代码,知道您还不知道的变量名称,您可以获得什么?

【讨论】:

    【解决方案3】:

    听起来您希望变量的名称成为变量本身的一部分。 C++ 不会在运行时给出变量名称。您在程序中使用的标识符仅指传递的值。

    您可以定义明确包含名称的对象类型:

    #include <iostream>
    #include <string>
    
    template< typename t >
    struct named_value {
        t value;
        std::string name;
    };
    
    template< typename t >
    void _( named_value< t > const &nv ) { // not a good name for a function
        std::cout << nv.name; // not a good semantic for a function
    }
    
    template< typename t >
    std::ostream &operator<< ( std::ostream &s, named_value< t > const &v ) {
        return s << v.value;
    }
    
    typedef named_value< int > named_int;
    
    void print (named_int p)
    {
       _(p); std::cout << "=" << p;
    }
    
    int main()
    {
       named_int a = { 1, "a" }, b = { 2, "b" };
       _(a); 
       std::cout << " = " << a;
       print(b);
    }
    

    http://ideone.com/AFHEq

    但是,你真的不应该写这样的程序。

    【讨论】:

    • 叫我老式的,我使用模板作为最后的手段。即想要一系列具有相似属性的类 - 如堆栈、队列
    • @EdHeal 没有理由认为他只想命名他的ints。这里避免使用模板有好处吗?
    • @EdHeal 因为为每个案例定义一个单独的类可以实现这一点。谢谢你的笑声。
    • 你可以这样做——但这不是我提倡的。你根本没有这样做。有人认为你关心的是你的工作保障。
    • @EdHeal LOL,你投了反对票,因为模板太难读了。确实是工作保障。 :D
    【解决方案4】:

    您需要以某种方式将信息传递给打印函数。

    struct named {
        int &x_;
        const char *n_;
        operator int () const { return x_; }
        named(int &x, const char *n) : x_(x), n_(n) {}
    };
    
    const char * name (int, const char *s) { return s; }
    const char * name (named &n, const char *s) { return n.n_; }
    
    #define _(x) std::cout << name(x, #x)
    
    void print (named p) {
        _(p); std::cout << " = " << p << std::endl;
    }
    #define print(x) print(named(x, #x))
    
    int main() {
       int a=1, b=2;
       _(a); std::cout << " = " << a << std::endl;
       print(b);
    }
    

    【讨论】:

    • 谢谢大家,我明白了很多东西。就像我说的,我只是在做一些练习。我定义了一类点,并且需要以这种格式“P(x,y)”“打印”点。我认为这是一个好主意,可以让程序更短、更易读,而不是每一个点都写 _(P); cout
    • @user1507571:但听起来 Wug 的解决方案正是您真正想要的:将 print 设为宏。
    猜你喜欢
    • 2012-09-08
    • 1970-01-01
    • 2012-10-10
    • 2011-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多