在其声明之上调用函数

时间:2012-08-06 09:46:59

标签: c++ class namespaces scope forward-declaration

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()
    {
    }
};

处理对声明之上的函数的调用不一致的原因是什么?为什么我可以在一个类中完成它,但不能在命名空间内或全局范围内?

5 个答案:

答案 0 :(得分:3)

您可以在类内部或类声明之后定义成员函数,也可以在每个函数中定义一些成员函数。

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

您的代码

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()
 {     }

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

答案 1 :(得分:1)

  1. 可以重新打开命名空间,并可以在任何地方添加新内容。 无法重新打开类 - 必须放入所有内容 单个地方。

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

  3. 你可以写

    namespace n
    {
        void foo();
    
        void bar()
        {
            foo();
        }
    
        void foo()
        {
        }
    }
    

    但不是

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

    因此,类需要更多这样的功能,并且为它们实现它比为命名空间更容易实现。

答案 2 :(得分:0)

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

另一方面,命名空间可以在大量不同的文件中使用它,你不能指望编译器查看它们,因为它首先不知道在哪里查看。

要避免这种情况,请使用function prototypes

答案 3 :(得分:0)

我不确定,但我的想法是class有点像对象(使用不当),其所有内部组件一起工作(一般来说),其成员肯定会需要它的方法。

但命名空间不同,功能不相关。这意味着函数不适用于命名空间内的所有其他函数。

因此,拆分声明和定义是你能做的最好的事情。

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

答案 4 :(得分: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 };
};