473,394 Members | 1,841 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Forward declaration allowed?

Hi,

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?

Consider the following code snippet:

class RGBA;

class Colour
{
public:
virtual RGBA ToRGBA() const = 0; // [1]
};

class RedComponent;

class RGBA : public Colour
{
public:
RGBA( double r, double g, double b, double a = 1.0 );
virtual RGBA ToRGBA() const;
RedComponent GetRed() const;
};
class HSV : public Colour
{
public:
HSV( double h, double s, double v, double a = 1.0 );
virtual RGBA ToRGBA() const;
};

int main()
{
RGBA red( 1.0, 0.0, 0.0 );
HSV papayaWhip( 37.0, 0.16, 1.0 );
RGBA c = papayaWhip.ToRGBA();
c.Red(); // << [2]
return 0;
}

Colour::ToRGBA can be declared to return an RGBA by value even though it is
only forward declared?

I understand the error at [2] in the call to c.Red() - RedComponent is
incomplete. But this is the error I would have expected at [1] - which
compiles cleanly in Visual Studio 2005 and gcc version 4.0.1 (Apple
Computer, Inc. build 5363)

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?

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?

Thanks for any insights...

--
Regards,
Steve.

Feb 22 '07 #1
4 5341
Steve wrote:
Hi,

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?
Forward declaration is good enough for this case.
>
Consider the following code snippet:

class RGBA;

class Colour
{
public:
virtual RGBA ToRGBA() const = 0; // [1]
};
[snip]

I think your confusion is that

virtual RGBA ToRGBA() const = 0; // [1]

is not a 'by-value use'. It's only a declaration. If you actually called
ToRGBA that would be a by-value use.

>
Thanks for any insights...
john
Feb 22 '07 #2
On Feb 22, 10:51 am, Steve <r...@127.0.0.1wrote:
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

Feb 22 '07 #3
On 22/2/07 19:39, in article Ej*******************@newsfe4-gui.ntli.net,
"John Harrison" <jo*************@hotmail.comwrote:
I think your confusion is that

virtual RGBA ToRGBA() const = 0; // [1]

is not a 'by-value use'. It's only a declaration. If you actually called
ToRGBA that would be a by-value use.
Yes, that is the evidence I was seeing, but couldn't quite understand it
fully.

Thanks very much for your quick reply.

--
Regards,
Steve

"...which means he created the heaven and the earth... in the DARK! How good
is that?"

Feb 22 '07 #4
On 22/2/07 19:57, in article
11**********************@t69g2000cwt.googlegroups. com, "Michael"
<mc******@aol.comwrote:
This is perfectly legitimate, with the possible exception of the 'u'
in 'Color.' :)
Have you a licence in correcting spelling non-mistakes? ;-)
<snipped a good explanation>

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
Got it! I think actually I was confusing this usage with case 2.

Thanks very much for your explanation.

--
Regards,
Steve

"...which means he created the heaven and the earth... in the DARK! How good
is that?"

Feb 22 '07 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Alexander Grigoriev | last post by:
Not quite new version of GCC that I have to use, craps with the following code: enum E; enum E { e }; That is, it doesn't accept forward declaration of enum. C++ standard text doesn't...
6
by: Kevin Grigorenko | last post by:
Hello, I have the definitions of classes A and B in a header file. Class A has a private member of type B. Class B is defined after class A in the header file. I place a forward declaration...
5
by: Stephane Routelous | last post by:
Hi, I would like to make a forward declaration of a strcuture nested in a class. I have file A.h class A { public: struct B
2
by: verec | last post by:
Consider a first version: --- drawable.hpp --- #include "gcdata.hpp" struct drawable { ... virtual int internal_new_GC(gcdata * gcd) = 0 ; } ; --- gcdata.hpp ---
11
by: Milind | last post by:
Hi, I was trying to implement a composition relation, somthing of the following type: class A { public: class B {
4
by: yuliy | last post by:
Hello gurus, I stuck in following: how can I do forward declaration if the forward declared class is in some namespace? something like // header class std::string; // approach#1
12
by: fox | last post by:
How do I (portably) make a forward reference to a static (I mean file-scope) variable? I've been using "extern" for years, for example: extern int x; int foo(void) { return x++; }
3
by: yancheng.cheok | last post by:
hello all, how can i make, a forward declaration class's enum member, being visible by another class? consider the following case, ---------------------------- dog.h...
11
by: Jef Driesen | last post by:
I have the following problem in a C project (but that also needs to compile with a C++ compiler). I'm using a virtual function table, that looks like this in the header file: typedef struct...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.