fredoverflow
fredoverflow

Reputation: 263078

calling functions above their 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()
    {
    }
};

What is the rationale behind this inconsistency of treating calls to functions above their declaration? How come I can do it inside a class, but not inside a namespace or at global scope?

Upvotes: 6

Views: 281

Answers (5)

Bo Persson
Bo Persson

Reputation: 92211

You can define member functions either inside the class, or after the class declaration, or some of each.

To get some consistency here, the rules for a class with functions defined inline is that it still has to be compiled as if the functions were defined after the class.

Your code

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

     static void bar()
     {     }
 }; 

compiles the same as

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

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

 void C::bar()
 {     }

and now there is no magic in the visibility, because the functions can all see everything declared in the class.

Upvotes: 3

TemplateRex
TemplateRex

Reputation: 70516

See the quote below from the Standard

3.3.7 Class scope [basic.scope.class]

1) The following rules describe the scope of names declared in classes. 1) The potential scope of a name declared in a class consists not only of the declarative region following the name’s point of declaration, but also of all function bodies, default arguments, and brace-or-equalinitializers of non-static data members in that class (including such things in nested classes).

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

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 };
};

Upvotes: 0

Tadeusz Kopec for Ukraine
Tadeusz Kopec for Ukraine

Reputation: 12403

  1. Namespaces can be reopened and new things can be added in any place. Classes cannot be reopened - all their contents must be put in single place.

  2. Function prototypes are legal in namespaces but not in classes.

You can write

namespace n
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

But not

class C
{
    void foo();

    void bar()
    {
        foo();
    }

    void foo()
    {
    }
}

So classes need such feature much more and it is much easier to implement it for them than for namespaces.

Upvotes: 1

Salepate
Salepate

Reputation: 327

I'm not sure but my thought is that a class is somewhat an object (badly used) where all its internal components work together (generally speaking), its member will definitely need its methods.

But a namespace is different, functions are not related. It means that a function isnt intended to work with every other functions inside the namespace.

So splitting declaration and definitions is the best thing you could do.

If foo() needs bar() its most likely going to be in the same declaration file, and would work that way

Upvotes: 0

SingerOfTheFall
SingerOfTheFall

Reputation: 29966

Well maybe because you have your class declaration in one place, and the compiler can easily obtain the information of it's members.

A namespace, on the other hand, can have it's stuff in tons of different files, and you can't expect the compiler to look through them, because it doesn't know where to look in the first place.

To avoid this, just use function prototypes.

Upvotes: 0

Related Questions