Do class functions/variables have to be declared before being used?

前端 未结 4 1907
孤独总比滥情好
孤独总比滥情好 2020-11-27 19:05

So I was learning about classes and I stumbled upon something I found was quite awkward to me.

class Nebla 
{
    public:
        int test()
        {
               


        
相关标签:
4条回答
  • 2020-11-27 19:44

    Besides Philip's good response, Stroustrup gives a nice explanation of Name Lookup Rules in The Design and Evolution of C++. This is described in "6.3 Clarifications". In 6.3.1.1, "The ARM Name Lookup Rules", he mentions 2 rules defined in the ARM:

    [1]The type redefinition rule:A type name may not be redefined in a class after it has been used there.

    [2] The rewrite rule: Member functions defined inline are analyzed as if they were defined immediately after the end of their class declarations.

    So in your case it would apply the rewrite rule (as Philip deduced), that's why you can forward reference those class members.

    This book may be mainly of historical interest (it's written in '94), but I think those rules are applied the same way today.

    0 讨论(0)
  • 2020-11-27 19:47

    The reason you are able to do this is because by the time you call test, printout or printout2, they will have already been created. If you call the function outside the arbitrary function before it's implementation, then you'll get an error.

    Think of class member-functions as being asynchronous with the flow of evaluation of the rest of the class. This won't work with stand alone functions, but you can access data members that haven't been instantiated yet. I'm not completely sure why we are able to do this, but I think it has to do with instantitation of the class object.

    0 讨论(0)
  • 2020-11-27 19:54

    Just to make it clear, this is required by the C++ Standard, not just the way several compilers handle class definitions.

    N3242 3.3.7:

    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, brace-or-equal-initializers of non-static data members, and default arguments in that class (including such things in nested classes).

    0 讨论(0)
  • 2020-11-27 19:56

    Good question; I've relied on that feature for years without thinking about it. I looked through several C++ books to find an answer, including Stroustrup's The C++ Programming Language and The Annotated C++ Reference Manual, but none acknowledge or explain the difference. But, I think I can reason through it.

    The reason, I believe, that your example works is that the bodies of your test and printout aren't truly where they appear in your file. The code

    class MyClass {
      void someFun() {
        x = 5;
      }
      int x;
    };
    

    ...which appears to violate the rule of having to declare variables before you use them, is actually equivalent to:

    class MyClass {
      void someFun();
      int x;
    };
    
    void MyClass::someFun() {
      x = 5;
    }
    

    Once we rewrite it like that, it becomes apparent that the stuff inside your MyClass definition is actually a list of declarations. And those can be in any order. You're not relying on x until after it's been declared. I know this to be true because if you were to rewrite the example like so,

    void MyClass::someFun() {
      x = 5;
    }
    
    class MyClass {
      void someFun();
      int x;
    };
    

    ...it would no longer compile! So the class definition comes first (with its complete list of members), and then your methods can use any member without regard for the order in which they're declared in the class.

    The last piece of the puzzle is that C++ prohibits declaring any class member outside of the class definition, so once the compiler processes your class definition, it knows the full list of class members. This is stated on p.170 of Stroustrup's The Annotated C++ Reference Manual: "The member list defines the full set of members of the class. No member can be added elsewhere."

    Thanks for making me investigate this; I learned something new today. :)

    0 讨论(0)
提交回复
热议问题