6
void foo()
{
    bar();          // error: ‘bar’ has not been declared
}

void bar()
{
}

namespace N
{
    void foo()
    {
        N::bar();   // error: ‘bar’ is not a member of ‘N’
    }

    void bar()
    {
    }
}

class C
{
    static void foo()
    {
        C::bar();   // works just fine
    }

    static void bar()
    {
    }
};

将函数调用置于其声明之上的这种不一致的原因是什么?为什么我可以在类中做到这一点,而不是在命名空间或全局范围内?

4

5 回答 5

3

您可以在类内部或在类声明之后定义成员函数,或者其中的一些。

为了在这里获得一些一致性,具有内联定义函数的类的规则是,它仍然必须像函数在类之后定义一样进行编译。

你的代码

class C {
     static void foo()
     {
         C::bar();   // works just fine 
     }

     static void bar()
     {     }
 }; 

编译相同

class C {
     static void foo();
     static void bar();
 }; 

 void C::foo()
 {  C::bar();  }

 void C::bar()
 {     }

现在可见性没有魔法了,因为函数都可以看到类中声明的所有内容。

于 2012-08-06T10:59:41.280 回答
1
  1. 命名空间可以重新打开,新的东西可以在任何地方添加。课程不能重新开放——所有内容必须放在一个地方。

  2. 函数原型在命名空间中是合法的,但在类中是不合法的。

你可以写

namespace n
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

但不是

class C
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

所以类更需要这样的特性,并且为它们实现它比为命名空间实现它要容易得多。

于 2012-08-06T10:13:27.420 回答
0

好吧,也许是因为你在一个地方有你的类声明,编译器可以很容易地获取它的成员的信息。

另一方面,命名空间可以在大量不同的文件中包含它的内容,并且您不能指望编译器浏览它们,因为它首先不知道在哪里查找。

为避免这种情况,只需使用函数原型

于 2012-08-06T09:52:26.830 回答
0

我不确定,但我的想法是 aclass在某种程度上是一个对象(使用不当),它的所有内部组件一起工作(一般来说),它的成员肯定需要它的方法。

但是命名空间不同,功能不相关。这意味着一个函数不打算与命名空间内的所有其他函数一起工作。

所以拆分声明和定义是你能做的最好的事情。

如果foo()需要bar()它最有可能在同一个声明文件中,并且会以这种方式工作

于 2012-08-06T09:57:57.470 回答
0

请参阅下面的标准报价

3.3.7 类范围[basic.scope.class]

1) 以下规则描述了类中声明的名称范围。1) 在类中声明的名称的潜在范围不仅包括名称声明点之后的声明区域,还包括其中的所有函数体、默认参数和非静态数据成员的大括号或均衡器类(包括嵌套类中的此类内容)。

2) 在类 S 中使用的名称 N 应在其上下文中引用相同的声明,并且在 S 的完整范围内重新评估时。对于违反本规则的情况不需要诊断。

typedef int c;
enum { i = 1 };

class X {
     char v[i]; // error: i refers to ::i
                // but when reevaluated is X::i
     int f() { return sizeof(c); } // OK: X::c
     char c;
     enum { i = 2 };
};
于 2012-08-06T11:01:50.733 回答