Declare but not define inner struct/class - legal C++ or not? - c++

Is following code legal C++ or not?
class Foo
{
class Bar;
void HaveADrink(Bar &bar);
void PayForDrinks(Bar &bar);
public:
void VisitABar(int drinks);
};
class Foo::Bar
{
public:
int countDrinks;
};
void Foo::HaveADrink(Bar &bar)
{
bar.countDrinks++;
}
void Foo::PayForDrinks(Bar &bar)
{
bar.countDrinks = 0;
}
void Foo::VisitABar(int drinks)
{
Bar bar;
for (int i=0; i<drinks; i++) HaveADrink(bar);
PayForDrinks(bar);
}
Both Visual C++ and GCC accepts it, however the code seems somewhat strange to me and I would hate to have it refused by some future compiler.
Still, the pattern seems useful to me to reduce compile time dependencies - I often use it to declare structs which are used to pass some "context" (a bunch of variables) which are shared between a few functions which all reside in the same cpp file, and this way I do not have to introduce the "context" definition into the public interface.

legal, and indeed usefull to hide implementation details to the outside world.

[edit]
I originally said this was the "pimpl idiom" : http://c2.com/cgi/wiki?PimplIdiom
but I agree that this is just part of pimpl is about. This technique is used by pimpl.
You're "forwarding" class Bar inside of class Foo. Perfectly legal as long as you don't do anything inside the definigino of Foo that would require the sizeof Bar. You can reference Bar using pointer or reference (Bar* or Bar&), but if you declare a data member in Foo such as this:
private:
Bar _bar;
It wouldn't work. The reason is because the definition of Foo must be enough to determine the sizeof Foo. Since the size of Bar is unknown inside the definition of Foo, it would make the size of Foo indeterminate. But using a pointer would work:
private:
Bar* _bar;
Because the sizeof of pointer is the same, and thus known, regardless of how Bar will be later defined.

Related

C++, why is forward declaration not required in structs/classes

In C++, why does the following compile:
struct test {
void foo() { this->bar++; }
int bar;
};
But not the following:
void foo() { bar++; }
int bar;
To be clear, I do understand that in the second case foo lacks a forward declaration of bar and does not compile. I however do not understand why the first one does not fail for the same reason.
In case of a structure, scope of the member variable is available within the structure. So if you define a function within a structure that variable will be available within the function.
But that is the not the case in second scenario.

Why does the Qt tutorial build the header class like this? [duplicate]

Is some one able to explain why header files have something like this?
class foo; // This here?
class bar
{
bar();
};
Do you need an include statement when using this?
Thanks.
The first class foo; is called a forward declaration of the class foo. It simply lets the compiler know that it exists and that it names a class. This makes foo what is called an "incomplete type" (unless the full declaration of foo has already been seen). With an incomplete type, you can declare pointers of that type, but you cannot allocate instances of that type or do anything that requires knowing its size or members.
Such forward declarations are frequently used when two types each may have pointers to each other, in which case both need to be able to express the notion of a pointer to the other type, and so you would have a circular dependency without such a thing. This is needed mostly because C++ uses a single pass mechanism for resolving types; in Java, you can have circular dependencies without forward declarations, because Java uses multiple passes. You may also see forward declarations where the author is under the misguided impression that using forward declarations instead of including the required header reduces compile time; that, of course, is not the case, because you need to include the full declaration (i.e. the header), anyway, and if preprocessor guards are used, then there is basically no difference in compile time.
To answer your question on whether you need the include or not... assuming you only need a partial type, then your header does not need to directly include the header for the type that has been forward declared; however, whoever makes use of your header, when they use your type will need to include the header for the forward declared type, and so you might as well just include the other header.
That's a forward declaration. You need it for example if class bar has a pointer to a foo object, but you don't want to include the whole definition of the foo object immediately.
this is a forward declaration of the class.
In my experience, this is typically done when you have a circular dependency.. for example
in foo.h
--------
#include "bar.h"
class foo
{
public:
foo(bar *bar);
private:
foo *m_foo;
};
and in bar.h
------------
class foo;
class bar
{
public:
void methodFooWillCall();
protected:
std::list<foo *> myFoos;
}
Just curious, why do we need the term forward declaration at all? Isn't a forward declaration simply a declaration (as opposed to a definition)?
class X; // declaration
class X // definition
{
int member;
void function();
};
That's a forward declaration. Consider the following example:
class foo; // you likely need this for the code beneath to compile
class bar {
void smth( foo& );
};
If you haven't included the definition of class foo in such a way that the compiler sees it before compiling the definition of class bar the code will not compile (the compiler will say it doesn't know what foo means) unless you have the forward declaration.
It's a forwards declaration of the class 'foo'. It allows you to declare pointers and references to the class, but not use it (eg. call members or determine its size), because it's not yet defined! It must later be followed up with a full, normal declaration (class foo { ... };).
It's useful for things like declaring two classes which hold pointers to each other, which otherwise would be impossible to set up.
This is called forward declaration. The body of the class foo would be defined at a later part of the file. Forward declaration is done to get around cyclic dependencies: The definition of class Bar requires class Foo and vice versa.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
As you can see, Bar has a reference to Foo and vice versa. If you try to compile this, the compiler will complaint saying that it doesn't know anything about Foo. The solution is to forward declare the class Foo above the Bar (just like you declare the prototype of a function above the main and define its body later).
class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
This is called a forward declaration. It is used to make your code aware that the class foo exists. This in turn can be used by the class bar.
It's commonly used to solve circular includes problems. Take this for example
//a.h
#include "b.h"
class A
{
void useB(B obj);
}
and
// b.h
#include "a.h"
class B
{
void useA(A obj);
}
This causes a circular include problem, because a.h includes b.h which in turns includes a.h, to infinity. You can solve this problem by making a forward declaration of each class in each header, like so :
//a.h
class B;
class A
{
void useB(B obj);
}
// b.h
class A;
class B
{
void useA(A obj);
}
Note : Very often when you have a circular include problem, this is indicative of a conception/modelling problem. You should probably ask yourself if your classes are well defined before trying to solve your problem with forward declarations.
Try to think of writing this:
file bar.h:
#include "bar.h"
class Foo
{
Bar* bar_ptr;
}
file foo.h:
#include "foo.h"
class Bar
{
Foo* foo_ptr;
}
This won't work, first due to infinite #include chain, then if you get rid of one of the includes, either Foo won't know what Bar is, or Bar won't know what Foo is.
Try this instead:
class Bar;
class Foo
{
Bar* bar_ptr;
};
file foo.h:
class Foo;
class Bar
{
Foo* foo_ptr;
};

Error c2036: unknown size only occurring in some situations

The code below compiles, even though I was expecting the compiler to complain that it doesn't know the size of Foo. However, if I replace the #include with a forward declaration of Bar, it doesn't compile for this reason.
I know that Foo is definitely only forward declared because if Foo* myfoo; is changed to Foo myfoo; then it does not compile. Why does this error only occur with a vector of objects of one type, but not the other?
Using Visual Studio Express 2013.
#include "Bar.h"
class Foo;
class MyClass{
Foo* myfoo;
std::vector<Foo> foos;
std::vector<Bar> bars;
};
In and of themselves, there is no reason that template type arguments need to be complete types (in fact, 14.3.1/2 explicitly states that this is not the case).
Such a requirement then comes from how that type is used within the definition of your type template (in this case, std::vector). For example, [C++11: 20.7.1/5] states that the template argument T of a std::unique_ptr<T> may be incomplete at the point of the unique_ptr's declaration; this is stated explicitly because it was not the case for std::auto_ptr.
You'll find that as soon as you try to do pretty much anything with your vector, you'll need that T to be complete. This issue is detectable at compile-time as it all comes down to the instantiation of templates, so your compiler will do the appropriate erroring as and when required.
The vector's destructor is usually one of those things.
So, using GCC 4.8, I cannot instantiate either vector with an incomplete value_type:
#include <vector>
class Foo;
class Bar;
std::vector<Foo> foos;
std::vector<Bar> bars;
int main() {}
error: invalid use of incomplete type 'class Foo'
error: invalid use of incomplete type 'class Bar'
Only when I use them as members in a class that never gets used is the entire thing compilable, because the vectors' destructors are never invoked and therefore never template-instantiated:
#include <vector>
class Foo;
class Bar;
class T
{
std::vector<Foo> foos;
std::vector<Bar> bars;
};
int main() {}
(no error)
Whatever your implementation does, it'll be the same for both Foo and Bar; if you're seeing a difference between them, then you must be doing something different with Bar that you have not shown us.
(I know its already answered, but I'm going to post mine any way)
A good way to think of this is, when does the definition of the class need to be known? In the case of vector<Foo>, the sizeof(Foo) needs to be known at reserve time, or access time, and the Foo::constructor and Foo::destructor information needs to be known when we add or remove items to the vector. And of course, it needs the Foo::destructor when the vector is being destroyed.
So this leads to one of the more common problems with forward declared template arguments to std::vector: you have a class above that uses a default constructor and a default destructor. When is the default destructor defined? Well (semantically, atleast) its defined when you don't define it in the class, so it is defined in this header file. More to the point, what is in that destructor? Hidden in every C++ destructor is clean up code that goes beyond the body of the destructor: it calls all the destructors of all members...but that means it tries to call the destructor for std::vector.
Are you SOL? Nope. The following should work just fine for you.
//myclass.hpp
class Foo;
class Bar;
class MyClass{
public:
MyClass();
~MyClass();
Foo* myfoo;
std::vector<Foo> foos;
std::vector<Bar> bars;
private:
};
//myclass.cpp
#include "myclass.hpp"
#include "Bar.h"
#include "Foo.h"
MyClass::MyClass(){};
MyClass::~MyClass(){};

How to instantiate a type named like a function

Apparently C++ lets you define both a struct/class and a function with the same name like this:
struct Foo {
int foo;
Foo(int foo) : foo(foo) {}
};
void Foo(int foo) {}
int main() {
// Works, calls function
Foo(42);
// Doesn't work - compiler error
Foo foo(42);
}
Is this the expected behaviour?
How to create a instance of the Foo struct?
How to avoid that some added library defining a function named like a type in your project causes compiler errors all over the place?
You can write struct or class when you mean the type:
struct Foo foo(42);
class Foo bar(0xdeadbeef);
Yes, this is expected. There is no general way to say "I meant the class, not the function, with this name" because you are not supposed to re-use names.
typename cannot help you here, though since Foo is a class and C++ provides backward compatibility with C's struct T type syntax, you can say class Foo or struct Foo instead:
int main() {
// Calls function
Foo(42);
// Constructs a `[class] Foo`
class Foo foo(42);
}
This is something of a hack, though, and doesn't really solve the fundamental problem which is that the symbols in your program are not clearly differentiated from one another.
Depending on your real circumstances, a namespace might solve your problem in a robust and clear way. Libraries should be using them (but often don't).
Otherwise simply improve your names... and I don't mean by calling one Foo and the other FooClass!

class foo; in header file

Is some one able to explain why header files have something like this?
class foo; // This here?
class bar
{
bar();
};
Do you need an include statement when using this?
Thanks.
The first class foo; is called a forward declaration of the class foo. It simply lets the compiler know that it exists and that it names a class. This makes foo what is called an "incomplete type" (unless the full declaration of foo has already been seen). With an incomplete type, you can declare pointers of that type, but you cannot allocate instances of that type or do anything that requires knowing its size or members.
Such forward declarations are frequently used when two types each may have pointers to each other, in which case both need to be able to express the notion of a pointer to the other type, and so you would have a circular dependency without such a thing. This is needed mostly because C++ uses a single pass mechanism for resolving types; in Java, you can have circular dependencies without forward declarations, because Java uses multiple passes. You may also see forward declarations where the author is under the misguided impression that using forward declarations instead of including the required header reduces compile time; that, of course, is not the case, because you need to include the full declaration (i.e. the header), anyway, and if preprocessor guards are used, then there is basically no difference in compile time.
To answer your question on whether you need the include or not... assuming you only need a partial type, then your header does not need to directly include the header for the type that has been forward declared; however, whoever makes use of your header, when they use your type will need to include the header for the forward declared type, and so you might as well just include the other header.
That's a forward declaration. You need it for example if class bar has a pointer to a foo object, but you don't want to include the whole definition of the foo object immediately.
this is a forward declaration of the class.
In my experience, this is typically done when you have a circular dependency.. for example
in foo.h
--------
#include "bar.h"
class foo
{
public:
foo(bar *bar);
private:
foo *m_foo;
};
and in bar.h
------------
class foo;
class bar
{
public:
void methodFooWillCall();
protected:
std::list<foo *> myFoos;
}
Just curious, why do we need the term forward declaration at all? Isn't a forward declaration simply a declaration (as opposed to a definition)?
class X; // declaration
class X // definition
{
int member;
void function();
};
That's a forward declaration. Consider the following example:
class foo; // you likely need this for the code beneath to compile
class bar {
void smth( foo& );
};
If you haven't included the definition of class foo in such a way that the compiler sees it before compiling the definition of class bar the code will not compile (the compiler will say it doesn't know what foo means) unless you have the forward declaration.
It's a forwards declaration of the class 'foo'. It allows you to declare pointers and references to the class, but not use it (eg. call members or determine its size), because it's not yet defined! It must later be followed up with a full, normal declaration (class foo { ... };).
It's useful for things like declaring two classes which hold pointers to each other, which otherwise would be impossible to set up.
This is called forward declaration. The body of the class foo would be defined at a later part of the file. Forward declaration is done to get around cyclic dependencies: The definition of class Bar requires class Foo and vice versa.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
As you can see, Bar has a reference to Foo and vice versa. If you try to compile this, the compiler will complaint saying that it doesn't know anything about Foo. The solution is to forward declare the class Foo above the Bar (just like you declare the prototype of a function above the main and define its body later).
class Foo; //Tells the compiler that there is a class Foo coming down the line.
class Bar
{
Foo * foo;
};
class Foo
{
Bar * bar;
};
This is called a forward declaration. It is used to make your code aware that the class foo exists. This in turn can be used by the class bar.
It's commonly used to solve circular includes problems. Take this for example
//a.h
#include "b.h"
class A
{
void useB(B obj);
}
and
// b.h
#include "a.h"
class B
{
void useA(A obj);
}
This causes a circular include problem, because a.h includes b.h which in turns includes a.h, to infinity. You can solve this problem by making a forward declaration of each class in each header, like so :
//a.h
class B;
class A
{
void useB(B obj);
}
// b.h
class A;
class B
{
void useA(A obj);
}
Note : Very often when you have a circular include problem, this is indicative of a conception/modelling problem. You should probably ask yourself if your classes are well defined before trying to solve your problem with forward declarations.
Try to think of writing this:
file bar.h:
#include "bar.h"
class Foo
{
Bar* bar_ptr;
}
file foo.h:
#include "foo.h"
class Bar
{
Foo* foo_ptr;
}
This won't work, first due to infinite #include chain, then if you get rid of one of the includes, either Foo won't know what Bar is, or Bar won't know what Foo is.
Try this instead:
class Bar;
class Foo
{
Bar* bar_ptr;
};
file foo.h:
class Foo;
class Bar
{
Foo* foo_ptr;
};