What does this symbol mean?
AirlineTicket::AirlineTicket()
:: is the scope resolution operator - used to qualify names. In this case it is used to separate the class AirlineTicket from the constructor AirlineTicket(), forming the qualified name AirlineTicket::AirlineTicket()
You use this whenever you need to be explicit with regards to what you're referring to. Some samples:
namespace foo {
class bar;
}
class bar;
using namespace foo;
Now you have to use the scope resolution operator to refer to a specific bar.
::foo::bar is a fully qualified name.
::bar is another fully qualified name. (:: first means "global namespace")
struct Base {
void foo();
};
struct Derived : Base {
void foo();
void bar() {
Derived::foo();
Base::foo();
}
};
This uses scope resolution to select specific versions of foo.
In C++ the :: is called the Scope Resolution Operator. It makes it clear to which namespace or class a symbol belongs.
It declares a namespace. So in AirlineTicket:: you can call all public functions of the AirlineTicket class and AirlineTicket() is the function in that namespace (in this case the constructor).
AirlineTicket is like a namespace for your class. You have to use it in the implementation of the constructor.
Related
Let's suppose I have a namespace Foo and I have declared a class Bar inside of it with a constructor inheriting a class Base with its constructor along with some other class Baz with a publicly accessible method boo():
namespace Foo {
class Baz {
public:
void boo();
};
class Base {
public:
Base();
};
class Bar: public Base {
public:
Bar();
};
}
Now I want to define the Bar constructor in my implementation as follows:
Foo::Bar::Bar(): Foo::Base::Base() {
Foo::Baz::boo();
}
It appears as though it's OK to write it down like this:
Foo::Bar::Bar(): Base() {
Baz::boo();
}
Meaning that once I specify the namespace in Foo::Bar::Bar() explicitly, there is no need to specify it later in the definition of this method.
Does it work like that everywhere from the explicit mentioning of the namespace up to the end of the definition?
If we look at your Bar constructor definition:
Foo::Bar::Bar(): Base() {
Baz::boo();
}
Once the declaration-part of the constructor (Foo:::Bar::Bar) have been read by the compiler, it knows the scope and it's no longer needed.
A more interesting example would be e.g.
namespace Foo
{
struct Baz {};
struct Bar
{
Baz fun(Baz);
};
}
Foo::Baz Foo::Bar::fun(Baz)
{
// Irrelevant...
}
Now, for the definition of the structure itself, Baz doesn't need any namespace-qualifier since it's defined in the namespace and all the symbols of the namespace is available directly.
The definition of the function fun is a different. Because it's not defined inside the namespace, we need to fully qualify the Baz structure for the return type. And the same for the actual function-name. But then like before once that part is read and parsed by the compiler, it knows the scope and knows that the argument Baz is really Foo::Baz.
You can read more about name lookup in this reference.
Consider a class inside a namespace. The definition of the class declares a friend function.
namespace Foo
{
class Bar
{
friend void baz();
};
}
This should, based on what I know, declare baz() as a member of the innermost enclosing namespace, i.e. Foo.
Therefore, I expected the following definition for baz() to be correct:
void Foo::baz() { }
However, GCC (4.7) gives me an error.
error: ‘void Foo::baz()’ should have been declared inside ‘Foo’
Several solutions seem to work:
Declare baz() outside the class.
namespace Foo
{
void baz();
class Bar
{
friend void baz();
};
}
Define baz() inside the namespace.
namespace Foo
{
class Bar
{
friend void baz();
};
}
...
namespace Foo
{
void baz() { }
}
Compile with the -ffriend-injection flag, which eliminates the error.
These solutions seem to be inconsistent with the general rules of declaration/definition in C++ I know.
Why do I have to declare baz() twice?
Why is the definition otherwise only legal inside a namespace, and illegal with the scope resolution operator?
Why does the flag eliminate the error?
Why do I have to declare baz() twice?
Because the friend declaration doesn't provide a usable declaration of the function in the namespace. It declares that, if that function is declared in that namespace, it will be a friend; and if you were to define a friend function inside a class, then it would be available via argument-dependent lookup (but not otherwise) as if it were declared in the namespace.
Why is the definition otherwise only legal inside a namespace, and illegal with the scope resolution operator?
Because it hasn't been (properly) declared in the namespace, and a function can only be defined outside its namespace (with scope resolution) if it has been declared.
Why does the flag eliminate the error?
Because the flag causes the friend declaration to act as a declaration in the namespace. This is for compatibility with ancient dialects of C++ (and, apparently, some modern compilers) in which this was the standard behaviour.
The first piece of code should compile:
namespace A {
struct B {
friend void foo();
};
}
void A::foo() {}
Although it that particular function cannot be used unless you also provide a declaration at namespace level. The reason is that friend declarations are only seen through Argument Dependent Lookup (ADL), but foo does not depend on A::B, and thus the compiler will never look inside that type.
What's the difference between these two declarations?
class foo
{
public:
static void bar();
};
and
namespace foo
{
void bar();
}
The way I see it, there is none, since bar in class foo doesn't have access to this, and neither does bar in namespace foo.
This is purely theoretical, of course.
What's the difference between a public static class member function and a global function declared in a namespace?
The class member function will be able to access private static member of the class, while a function inside a namespace will not directly have any kind of data protection
As pointed out by #ValarDohaeris, you can create an object of class foo and call obj.bar() even in an object context, while the same cannot be achieved with namespaces as there are no instances of namespaces
The namespace can be imported via using making bar() a valid call
As mentioned by #John5342 you can use the class foo at template argument. For example in template<typename T> fun() { T::bar(); }
Functions defined at namespace scope can be found via argument dependent lookup:
namespace foo
{
class bar;
void baz (bar);
}
foo::bar x;
baz (x); // Ok, baz is found by ADL
If foo is a class instead of a namespace, this does not work.
I've two question about this code bellow:
namespace A { class window; }
void f(A::window);
namespace A
{
class window
{
private:
int a;
friend void ::f(window);
};
}
void f(A::window rhs)
{
std::cout << rhs.a << std::endl;
}
1) why do I need to qualify the member function f inside window class to be global by doing ::f(window) ?
2) why do I need to predeclare the function f(A::window) in this particular case, whereas when the class is not defined inside a namespace it's ok for the function to be declared after the function is declared a friend.
When you declare f() as a friend it's actually done in the enclosing namespace of the containing class (A in this case) if a forward declaration is not already present.
So this...
namespace A
{
class window
{
private:
friend void ::f(window);
};
}
essentially becomes this...
namespace A
{
class window;
void f(window);
class window
{
private:
friend void f(window);
};
}
Edit: Here is a snippet from the C++ standard that explicltly talks about this scenario:
Standard 7.3.1.2 / 3 :
Every name first declared in a namespace is a member of that namespace. If a friend declaration in a nonlocal class first declares a class or function the friend class or function is a member of the innermost enclosing namespace. The name of the friend is not found by unqualified lookup (3.4.1) or by qualified lookup (3.4.3) until a matching declaration is provided in that namespace scope (either before or after the class definition granting friendship).
As for 1), your function is not in the namespace, so you must use :: to tell the compiler to search it outside the namespace.
Otherwise, it will only look for function inside the namespace (that's why they exist). Koenig lookup doesn't apply here, as window class is inside the namespace.
not too sure about 2) though, but i bet it is related to 1).
1) because function f is declared and defined outside of the current namespace. If you moved the definition of your class into the same namespace as the function whether global or otherwise you wouldn't need to.
2) you always need to declare a function before it is referenced. Your class references the function with the friend statement.
the following code will help me illustate my question to you directly:
#include<iostream>
class foo {
public:
class bar {
public:
bar(int a) : m_a(a) {}
void say() { std::cout << m_a << std::endl;}
private:
int m_a;
};
};
int main()
{
foo::bar b(3);
b.say();
}
as you see, to declare a object of class bar, we use the quite namespace like syntax "foo::bar", although actually bar is just an embebed class type in class foo. my question
is does the scope of a class itself is a namespace in c++?
No, a class is not a namespace. A class does form a declarative region, though.
You use the same syntax (the :: operator) to refer to names declared at class scope as you do to refer to names declared at namespace scope.
The class is not a namespace, it is a scope. You already used this term yourself. Namespace is a scope. Class is a scope as well. The :: operator is a scope resolution operator. Scope, not namespace, is the fundamental term that can act as a "common denominator" in this case. Scope is the reason why you can use the :: operator with both classes and namespaces on the left-hand side.
Another interesting distinction between classes and namespaces is that a namespace can be declared over multiple files and in multiple parts, but a class cannot. For example, you could do:
File a.hpp:
namespace Foo {
int memberA;
}
File b.hpp:
namespace Foo {
int memberB;
}
...
namespace Foo {
int memberC;
}
The scope of a class is not the same as the scope of a namespace. Classes can be templated, which affects the definitions in its scope. Classes can also have definitions that are only able to be used within that scope (private and protected).
The class name itself is not a namespace, although the scoping operator treats it as such, or almost as such anyways.