473,382 Members | 1,733 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,382 software developers and data experts.

What's the rule for using forward declarations?

I'm hoping someone can please help me remember the C++ rule: When
you're writing a header file for a class (say, some_namespace::Bar),
and that class makes use of another class (some_namespace::Foo),

-------------------------------- snip --------------------------------
#ifndef GUARD_Foo_HPP
#define GUARD_Foo_HPP

namespace some_namespace {

class Foo
{
// Stuff.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------
you have the option of either #including Foo.hpp,
-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

#include Foo.hpp

namespace some_namespace {

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

or else just making a forward declaration:

-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

namespace some_namespace {

// NOTE: We're *inside* the namespace declaration for this:
class Foo;

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

I realize that using the forward declaration is always preferable
(so as to make fewer dependencies, as well as less work for the
preprocessor and compiler), but what's the rule for when I can get
away with it?

Thanks.
--
--- remove zees if contacting via email ---

Jul 22 '05 #1
5 1860
John Gabriele wrote:
I'm hoping someone can please help me remember the C++ rule: When
you're writing a header file for a class (say, some_namespace::Bar),
and that class makes use of another class (some_namespace::Foo),

-------------------------------- snip --------------------------------
#ifndef GUARD_Foo_HPP
#define GUARD_Foo_HPP

namespace some_namespace {

class Foo
{
// Stuff.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------
you have the option of either #including Foo.hpp,
-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

#include Foo.hpp

namespace some_namespace {

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

or else just making a forward declaration:

-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

namespace some_namespace {

// NOTE: We're *inside* the namespace declaration for this:
class Foo;

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

I realize that using the forward declaration is always preferable
(so as to make fewer dependencies, as well as less work for the
preprocessor and compiler), but what's the rule for when I can get
away with it?

Thanks.

Basically you can get away with it as long as you only have pointers and
references in your header. If you have declarations of user defined types
(insted of pointers or references to them), because of the rules for
instantiating these types where they are declared, the compiler has to have
the full definition of the type available in order to allocate memory.
Does this make sense?
--
"[M]y dislike for the preprocessor is well known. Cpp is essential in C
programming, and still important in conventional C++ implementations, but
it is a hack, and so are most of the techniques that rely on it. ...I think
the time has come to be serious about macro-free C++ programming." - B. S.

Jul 22 '05 #2
"John Gabriele" <jo*****@bestwebz.net> wrote in message
news:10*************@corp.supernews.com...
<snip>
or else just making a forward declaration:

-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

namespace some_namespace {

// NOTE: We're *inside* the namespace declaration for this:
class Foo;

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

I realize that using the forward declaration is always preferable
(so as to make fewer dependencies, as well as less work for the
preprocessor and compiler), but what's the rule for when I can get
away with it?


You can "get away" with a forward declaration when the code that relies on
it is using the type "in name only". That basically means that the code
doesn't need to know the size of the type or the members of the type. This
generally occurs when the type is only being passed around by
pointer/reference. For example, suppose the following was inline inside
your "Bar" class definition:

void foo( Foo* p ) { // OK
p->memfun(); // error
}

void foo2() {
Foo f; // error
}

The FAQ (http://www.parashift.com/c++-faq-lite/) talks about forward
declarations a bit in section 38 ("Miscellaneous technical issues")
questions 11 through 14.

--
David Hilsee
Jul 22 '05 #3
David Hilsee wrote:
"John Gabriele" <jo*****@bestwebz.net> wrote in message
news:10*************@corp.supernews.com...
<snip>
or else just making a forward declaration:

-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

namespace some_namespace {

// NOTE: We're *inside* the namespace declaration for this:
class Foo;

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

I realize that using the forward declaration is always preferable
(so as to make fewer dependencies, as well as less work for the
preprocessor and compiler), but what's the rule for when I can get
away with it?

You can "get away" with a forward declaration when the code that relies on
it is using the type "in name only". That basically means that the code
doesn't need to know the size of the type or the members of the type. This
generally occurs when the type is only being passed around by
pointer/reference. For example, suppose the following was inline inside
your "Bar" class definition:

void foo( Foo* p ) { // OK
p->memfun(); // error
}

void foo2() {
Foo f; // error
}

The FAQ (http://www.parashift.com/c++-faq-lite/) talks about forward
declarations a bit in section 38 ("Miscellaneous technical issues")
questions 11 through 14.


Ahh. Thanks Dave (and also Steve). That makes sense.

Also, thanks for the link to the faq. I just dug out my
old dead-tree version, but it looks like there's been many
updates to it since publication in 1999. :)

---J

--
--- remove zees if contacting via email ---

Jul 22 '05 #4

"David Hilsee" <da*************@yahoo.com> wrote in message
news:E7********************@comcast.com...
"John Gabriele" <jo*****@bestwebz.net> wrote in message
news:10*************@corp.supernews.com...
<snip>
or else just making a forward declaration:

-------------------------------- snip --------------------------------
#ifndef GUARD_Bar_HPP
#define GUARD_Bar_HPP

namespace some_namespace {

// NOTE: We're *inside* the namespace declaration for this:
class Foo;

class Bar
{
// Stuff -- some of which uses Foo's.
};

} // namespace some_namespace.

#endif // GUARD_Bar_HPP
-------------------------------- snip --------------------------------

I realize that using the forward declaration is always preferable
(so as to make fewer dependencies, as well as less work for the
preprocessor and compiler), but what's the rule for when I can get
away with it?
You can "get away" with a forward declaration when the code that relies on
it is using the type "in name only".


-snip -
void foo( Foo* p ) { // OK
p->memfun(); // error
}


Pardon my ignorance, but when would someone use a type by "name only"? To me
it seems useless to forward declare a class when its member
functions/variables are inaccessable.
Jul 22 '05 #5
"Method Man" <a@b.c> wrote in message
news:K8******************@read1.cgocable.net...
<snip>
void foo( Foo* p ) { // OK
p->memfun(); // error
}

Pardon my ignorance, but when would someone use a type by "name only"? To

me it seems useless to forward declare a class when its member
functions/variables are inaccessable.


The FAQ has a good example where it is necessary to use forward declarations
in question 38.11 (referenced in my other post). They are also useful for
eliminating compilation dependencies, which is what John Gabriele seems to
be doing. This is the logic behind the pimpl idiom
(http://www.gotw.ca/gotw/024.htm). If you can forward declare a class in a
header instead of defining it in the header, then you won't have to
recompile as many source files when the definition of that class changes. I
have also used "opaque pointers" in C to provide a bit of encapsulation.
One module provided a forward declaration for a type that is used as a
"handle" to something that it didn't want other modules modifying or
depending upon its representation. To do anything with it, the other
modules had to pass the handle to the module that provided it.

--
David Hilsee
Jul 22 '05 #6

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

Similar topics

3
by: mjm | last post by:
Folks, Please help me with the following problems: ******************************************** 1. I have a class template template<class Base> class Matrix : public Base { /* .... */ }
1
by: Michael | last post by:
Ok, I'm just checking i'm on the right lines: sorry if i make a mistake with any strict definitions of things in a .h , try and put: class declaration (prototype) relevant forward...
44
by: Neil Cerutti | last post by:
In Rob Pike's style guide he urges the following: Simple rule: include files should never include include files. If instead they state (in comments or implicitly) what files they need...
1
by: Steve | last post by:
Can anyone explain why C++ .NET compiler throws error for the following code segment: // Forward declaration of ListViewItemComparer class public __gc class ListViewItemComparer ; public __gc...
2
by: Neo | last post by:
Hi, I am new to C++ and want to know what are forward declarations and any site which has a good introductory explanation. thanks in advance, nick
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++; }
2
by: Carlos Martinez Garcia | last post by:
Hi all: I usually make forward declarations in headers. Something like this: class MyClass; Now, I need a reference to a type defined like this (traditional C Style): typedef struct {
8
by: The Cool Giraffe | last post by:
One thing i do know for sure. When one creates a CPP file, one needs to include the H file. Now, having said that, i wonder if there are some general hints, requirements or standard guide lines on...
0
by: Rune Allnor | last post by:
Hi all. I have these classes, implemented as templates in header files. Right now I have one file per class, where both the declarations and implementations of one class are located in each...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
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
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
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...

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.