Re: Forward declaration allowed?
On Feb 22, 10:51 am, Steve <r...@127.0.0.1> wrote:
I always though to return an instance of a class by value, it had to be
defined - i.e. forward declaration isn't good enough?
This is a common misperception, even among regulars to this group.
Consider the following code snippet:
class RGBA;
class Colour
{
public:
virtual RGBA ToRGBA() const = 0; // [1]
};
This is perfectly legitimate, with the possible exception of the 'u'
in 'Color.' :)
<snip>
Colour::ToRGBA can be declared to return an RGBA by value even though it is
only forward declared?
Yes.
You must, however, have the full definition at the call site. So for
example:
// newfile.cpp
#include "Colour.h" /* forward declaration of RGBA */
#include "MyColour.h" /* class implementing Colour, with forward
declaration of RGBA */
int main() {
MyColor mc;
RGBA x = mc.ToRGBA(); /* <- Error, RGBA is not defined!!!! */
}
Is it because Colour::ToRGBA is only declared here, and RGBA must be fully
defined at it's definition, but only requires a declaration elsewhere? Or
is this something special to do with pure virtuals?
The former. You need the full definition 1) in the definition of
ToRGBA and 2) at any point where you call ToRGBA.
I was always taught that a forward declaration is good enough for a pointer
or reference use, but a by-value use required the full class's definition?
You need the full definition of a class C only in a couple cases:
1) You inherit from C
2) You have a member variable of type C
3) Your implementation uses an object of type C or uses the internals
of type C
This is the difference between using C "in size" (1 & 2 & 3) or "in
name only" (pointers, references, and declarations of function
parameters).
The compiler needs to know the size of type C if you inherit, so it
can calculate the size of your inherited class. It needs to know the
size of type C if you have a member variable of type C, so it can
calculate the size of the class (note that this doesn't apply if your
member variable is a pointer or a reference), and of course, where
your implementation uses an object of type C (automatic or with new),
or uses C.xyz. It also needs the size when you call a function with a
parameter of type C or a return value of type C, but that requirement
is only at the call site, not at the declaration.
Michael