473,657 Members | 2,507 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 1872
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*****@bestwe bz.net> wrote in message
news:10******** *****@corp.supe rnews.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 ("Miscellane ous technical issues")
questions 11 through 14.

--
David Hilsee
Jul 22 '05 #3
David Hilsee wrote:
"John Gabriele" <jo*****@bestwe bz.net> wrote in message
news:10******** *****@corp.supe rnews.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
preprocesso r 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 ("Miscellane ous 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******** ************@co mcast.com...
"John Gabriele" <jo*****@bestwe bz.net> wrote in message
news:10******** *****@corp.supe rnews.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******** **********@read 1.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
5462
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
1305
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 declarations for pointers in the class, #includes required for the objects aggregated in the class #includes required for base-classes #includes for templates
44
3372
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 to have included first, the problem of deciding which files to include is pushed to the user (programmer) but in a way that's easy to handle and that, by construction, avoids multiple inclusions. I was startled by this guideline, since...
1
2318
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 class CProgramLoaderForm : public System::Windows::Forms::Form { ListViewItemComparer* m_ListViewItemComparer ;
2
1646
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
12159
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
508
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
2135
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 what and how to include. Suppose that we have a project consisting of a number of classes and structs. Some of them using the others, some using all of them. What is a good approach when including? --
0
1467
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 file. I would like to apply the visitor pattern to some of these classes. One of the technicalities behind the visitor pattern is that one needs forward declarations of classes, since there are two class hierarchies which refer to each other.
0
8825
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8605
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7324
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6163
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 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 a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5632
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4151
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2726
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1953
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
2
1611
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.