Take, for example, the following code:
#include <iostream>
#include <string>
int main()
{
print("Hello!");
}
void print(std::string s) {
std::cout << s << std::endl;
}
When trying to build this, I get the following:
program.cpp: In function ‘int main()’:
program.cpp:6:16: error: ‘print’ was not declared in this scope
Which makes sense.
So why can I conduct a similar concept in a struct, but not get yelled at for it?
struct Snake {
...
Snake() {
...
addBlock(Block(...));
}
void addBlock(Block block) {
...
}
void update() {
...
}
} snake1;
Not only do I not get warnings, but the program actually compiles! Without error! Is this just the nature of structs? What's happening here? Clearly addBlock(Block) was called before the method was ever declared.
A struct in C++ is actually a class definition where all its content is public, unless specified otherwise by including a protected: or private: declaration.
When the compiler sees a class or struct, it first digests all its declarations from inside the block ({}) before operating on them.
In the regular method case, the compiler hasn't yet seen the type declared.
C++ standard 3.4.1:
.4:
A name used in global scope, outside of any function, class or
user-declared namespace, shall be declared before its use in global
scope.
This is why global variables and functions cannot be used before an afore declaration.
.5:
A name used in a user-declared namespace outside of the definition of
any function or class shall be declared before its use in that
namespace or before its use in a namespace enclosing its namespace.
same thing just written again as the .4 paragraph explictely restricted its saying to "global", this paragraph now says "by the way, its true as well in namespeces folks..."
.7:
A name used in the definition of a class X outside of a member
function body or nested class definition29 shall be declared in one of
the following ways: — before its use in class X or be a member of a
base class of X (10.2), or — if X is a nested class of class Y (9.7),
before the definition of X in Y, or shall be a member of a base class
of Y (this lookup applies in turn to Y ’s enclosing classes, starting
with the innermost enclosing class),30 or — if X is a local class
(9.8) or is a nested class of a local class, before the definition of
class X in a block enclosing the definition of class X, or — if X is a
member of namespace N, or is a nested class of a class that is a
member of N, or is a local class or a nested class within a local
class of a function that is a member of N, before the definition of
class X in namespace N or in one of N ’s enclosing namespaces.
I think this speaks of all the code that does not stand in cpu executed code (eg declarative code).
and finally the interesting part:
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, brace-or-equal-initializers of non-static data members, and
default arguments 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.
3)
If reordering member declarations in a class yields an alternate valid
program under (1) and (2), the program is ill-formed, no diagnostic is
required.
particularly, by the last point they use a negative manner to define that "any ordering is possible" because if re-ordering would change lookup then there is a problem. its a negative way of saying "you can reorder anything and its ok, it doesnt change anything".
effectively saying, in a class, the declaration is looked-up in a two-phase compilation fashion.
"why can I conduct a similar concept in a struct, but not get yelled at for it?"
In a struct or class definition you're presenting the public interface to a class and it's much easier to understand, search and maintain/update that API if it's presented in:
a predictable order, with
minimal clutter.
For predictable order, people have their own styles and there's a bit of "art" involved, but for example I use each access specifier at most once and always public before protected before private, then within those I normally put typedefs, const data, constructors, destructors, mutating/non-const functions, const functions, statics, friends....
To minimise clutter, if a function is defined in the class, it might as well be without a prior declaration. Having both tends only to obfuscate the interface.
This is different from functions that aren't members of a class - where people who like top-down programming do use function declarations and hide the definitions later in the file - in that:
people who prefer a bottom-up programming style won't appreciate being forced to either have separate declarations in classes or abandon the oft-conflicting practice of grouping by access specifier
Classes are statistically more likely to have many very short functions, largely because they provide encapsulation and wrap a lot of trivial data member accesses or provide operator overloading, casting operators, implicit constructors and other convenience features that aren't relevant to non-OO, non-member functions. That makes a constant forced separation of declarations and definitions more painful for many classes (not so much in the public interfaces where definitions might be in a separate file, but definitely for e.g. classes in anonymous namespaces supporting the current translation unit).
Best practice is for classes not to cram in a wildly extensive interface... you generally want a functional core and then some discretionary convenience functions, after which it's worth considering what can be added as non-member functions. The std::string is an often claimed to have too many member functions, though I personally think it's quite reasonable. Still, this also differs from a header file declaring a library interface, where exhaustive functionality can be expected to be crammed together making a separation of even inline implementation more desirable.
Related
This question already has answers here:
Namespace + functions versus static methods on a class
(9 answers)
Closed 3 years ago.
I've got a bunch of functions(func1(),func2(),...) in a header file to which I want to give some scope. I know of 2 implementations:
class bunchOfFunctions
{
public:
static void func1();
static void func2();
...
};
namespace bunchOfFunctions
{
void func1();
void func2();
...
};
In both the options, I can access the functions in the same way i.e. by bunchOfFunctions::func(). I prefer the namespace method(lesser typing), but I've seen the 1st method of implementation also at my workplace.
Which option is better? Is there any other option?
Apart from StroryTeller highlighted points,
Spread: A namespace can be spread into multiple files where as Class must be defined in a single place.
Readability and Understandability: Generally developers inherent understanding of what a Class is and what a namespace is.
"Better" depends on your definition for better. What qualities are you looking for in the scoping? There is no one size fits all answer here. But here are some properties of both approaches:
Necessity to qualify the function name.
With a class you must write bunchOfFunctions::func1() when
utilizing those functions. Meanwhile a namespace allows you to pull
a function in with a using declaration
using bunchOfFunctions::func1;
and use it unqualified in most scopes. If you wished you could even make all the members of the namespace available to unqualified name lookup with a using directive. Classes don't have an equivalent mechanic.
Aliasing.
There is no difference. To alias the class one writes
using BOF = bunchOfFunctions;
while aliasing the namespace is done with
namespace BOF = bunchOfFunctions;
Privacy.
A class can have private members. So you could put function declarations in there under a private access specifier and use them in public inline members. Namespaces have no such mechanism. Instead we rely on convention and put declarations under a "do not touch this" internal namespace, often called bunchOfFunctions::detail.
Argument dependent lookup.
C++ has a mechanism that allows it to find function declarations from an unqualified call, by examining the namespaces that contain the arguments to the call. For that to work, the function must be in an actual namespace. Static members of classes are not subject to such a lookup. So for any member types you may have, only a namespace will allow calls via ADL.
These four are off the top of my head. Judge your needs for yourself. As for "Is there any other option?", those are the only two ways you have to group such functions in C++ today. In C++20, we'll have modules! That will offer another level of grouping for code.
In addition the information given above I would add that going back to the standard definition of what a class and what a namespace is can help with decisions like this.
A namespace is a declarative region that provides a scope to the identifiers (the names of types, functions, variables, etc) inside it. Namespaces are used to organize code into logical groups and to prevent name collisions that can occur especially when your code base includes multiple libraries.
In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).
While these may sound similar they are rather specific. So if your functions are related, but not necessarily to the same object I would think hard about whether to put them in a class; particularly if grouping these functions together in a class may violate the Single Responsibility Principle: https://en.wikipedia.org/wiki/Single_responsibility_principle
This question here piqued my interest a little. Is there anywhere in the C++ standard that specifies all declarations within a class must be parsed before any accompanying implementations of member functions? I've seen a few other questions similar to this but no references to the standard in any of the answers.
The Standard doesn't specify how the compiler should parse a translation unit. Instead, it specifies everywhere it is and is not valid to use any identifier to refer to a declaration.
3.3.2p5:
After the point of declaration of a class member, the member name can be looked up in the scope of its
class. [ Note: this is true even if the class is an incomplete class. ]
3.3.7p1:
The following rules describe the scope of names declared in classes.
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).
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.
If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
A name declared within a member function hides a declaration of the same name whose scope extends to or past the end of the member function’s class.
The potential scope of a declaration that extends to or past the end of a class definition also extends to the regions defined by its member definitions, even if the members are defined lexically outside the class (this includes static data member definitions, nested class definitions, member function definitions (including the member function body and any portion of the declarator part of such definitions which follows the declarator-id, including a parameter-declaration-clause and any default arguments (8.3.6).
[class.mem] says:
-2- A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.
For the class to be complete within function bodies then in general all declaration need to be parsed: without completely parsing all declaration you can't know if something that wasn't parsed would change the meaning. Although, possibly related to that is [basic.scope.class]/1 which says:
3) If reordering member declarations in a class yields an alternate valid program under (1) and (2), the program is ill-formed, no diagnostic is required.
That means certain declarations could be used without parsing the entire class, because if another later declaration altered the meaning then the program would be ill-formed.
Of course the "as if" rule allows the compiler to choose any implementation as long as the user can't tell the difference, so maybe a compiler could choose to parse function bodies and then parse definitions as needed, but it would be hard to tell what's needed to process the member function definition (consider a function call which might call one of several overloaded functions, possibly involving enable_if-type tricks.)
This is the draft which explains C++ Programming Language Standard.
Programming Language C++ PDF
I think page 220 has some explanations on member functions.
I was interested to note that C++ (VSVC++ 2008 specifically) lets me declare a struct inline in a method.
e.g:
MyClass::method()
{
struct test{ int x;};
test t = {99};
}
My question is, how does this declaration work internally, and specifically does it have any negative performance implications?
how does this declaration work internally?
Exactly like a declaration at namespace scope, except that the name is only visible within the scope of the block it's declared in (in this case, the function body). UPDATE: as #Nawaz points out, there are one or two extra restrictions that apply to local classes: they cannot have static data members, and (in C++03, but not C++11) they can't be used as template type arguments.
does it have any negative performance implications?
No, apart from its scope (which only affects whether or not the code compiles), it is identical to any other class definition.
The main difference from defining the type inside the function scope or outside of it is, well, the scope. That is, if it is defined inside the function it will not be accessible outside of the function.
There are other differences though (at least in C++03, I have not rechecked C++11), you cannot have a static member or a template member in a local class. You cannot use that local class as argument to a template either (this limitation has been removed in C++11), and IIRC this is because the local class has internal linkage (rather than external for a namespace level class), and templates required the arguments to be of external linkage.
I was under the impression that everything in C++ must be declared before being used.
In fact, I remember reading that this is the reason why the use of auto in return types is not valid C++0x without something like decltype: the compiler must know the declared type before evaluating the function body.
Imagine my surprise when I noticed (after a long time) that the following code is in fact perfectly legal:
[Edit: Changed example.]
class Foo
{
Foo(int x = y);
static const int y = 5;
};
So now I don't understand:
Why doesn't the compiler require a forward declaration inside classes, when it requires them in other places?
The standard says (section 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).
This is probably accomplished by delaying processing bodies of inline member functions until after parsing the entire class definition.
Function definitions within the class body are treated as if they were actually defined after the class has been defined. So your code is equivalent to:
class Foo
{
Foo();
int x, *p;
};
inline Foo::Foo() { p = &x; }
Actually, I think you need to reverse the question to understand it.
Why does C++ require forward declaration ?
Because of the way C++ works (include files, not modules), it would otherwise need to wait for the whole Translation Unit before being able to assess, for sure, what the functions are. There are several downsides here:
compilation time would take yet another hit
it would be nigh impossible to provide any guarantee for code in headers, since any introduction of a later function could invalidate it all
Why is a class different ?
A class is by definition contained. It's a small unit (or should be...). Therefore:
there is little compilation time issue, you can wait until the class end to start analyzing
there is no risk of dependency hell, since all dependencies are clearly identified and isolated
Therefore we can eschew this annoying forward-declaration rule for classes.
Just guessing: the compiler saves the body of the function and doesn't actually process it until the class declaration is complete.
unlike a namespace, a class' scope cannot be reopened. it is bound.
imagine implementing a class in a header if everything needed to be declared in advance. i presume that since it is bound, it was more logical to write the language as it is, rather than requiring the user to write forwards in the class (or requiring definitions separate from declarations).
This question already has answers here:
Do class functions/variables have to be declared before being used?
(5 answers)
Closed 4 years ago.
I'm wondering why the declare-before-use rule of C++ doesn't hold inside a class.
Look at this example:
#ifdef BASE
struct Base {
#endif
struct B;
struct A {
B *b;
A(){ b->foo(); }
};
struct B {
void foo() {}
};
#ifdef BASE
};
#endif
int main( ) { return 0; }
If BASE is defined, the code is valid.
Within A's constructor I can use B::foo, which hasn't been declared yet.
Why does this work and, mostly, why only works inside a class?
Well, to be pedantic there's no "declare before use rule" in C++. There are rules of name lookup, which are pretty complicated, but which can be (and often are) roughly simplified into the generic "declare before use rule" with a number of exceptions. (In a way, the situation is similar to "operator precedence and associativity" rules. While the language specification has no such concepts, we often use them in practice, even though they are not entirely accurate.)
This is actually one of those exceptions. Member function definitions in C++ are specifically and intentionally excluded from that "declare before use rule" in a sense that name lookup from the bodies of these members is performed as if they are defined after the class definition.
The language specification states that in 3.4.1/8 (and footnote 30), although it uses a different wording. It says that during the name lookup from the member function definition, the entire class definition is inspected, not just the portion above the member function definition. Footnote 30 additionally states though that the lookup rules are the same for functions defined inside the class definition or outside the class definition (which is pretty much what I said above).
Your example is a bit non-trivial. It raises the immediate question about member function definitions in nested classes: should they be interpreted as if they are defined after the definition of the most enclosing class? The answer is yes. 3.4.1/8 covers this situation as well.
"Design & Evolution of C++" book describes the reasoning behind these decisions.
That's because member functions are compiled only after the whole class definition has been parsed by the compiler, even when the function definition is written inline, whereas regular functions are compiled immediatedly after being read. The C++ standard requires this behaviour.
I don't know the chapter and verse of the standard on this.
But if you would apply the "declare before use" rule strictly within a class, you would not be able to declare member variables at the bottom of the class declaration either. You would have to declare them first, in order to use them e.g. in a constructor initialization list.
I could imagine the "declare before use" rule has been relaxed a bit within the class declaration to allow for "cleaner" overall layout.
Just guesswork, as I said.
The most stubborn problems in the definition of C++ relate to name lookup: exactly which uses of a name refer to which declarations? Here, I'll describe just one kind of lookup problem: the ones that relate to order dependencies between class member declarations. [...]
Difficulties arise because of conflicts between goals:
We want to be able to do syntax analysis reading the source text once only.
Reordering the members of a class should not change the meaning of the class.
A member function body explicitly written inline should mean the same thing when written out of line.
Names from an outer scope should be usable from an inner scope (in the same way as they are in C).
The rules for name lookup should be independent of what a name refers to.
If all of these hold, the language will be reasonably fast to parse, and users won't have to worry about these rules because the compiler will catch the ambiguous and near ambiguous cases. The current rules come very close to this ideal.
[The Design And Evolution Of C++, section 6.3.1 called Lookup Issues on page 138]