I am looking for a nice book, reference material which deals with forward declaration of classes esp. when sources are in multiple directories, eg. class A in dirA is forward declared in class B in dirB ? How is this done ?
Also, any material for template issues, advanced uses and instantation problems, highly appreicated ?
Thanks.
Forward declarations have nothing to do with the directory structure of your project. You can forward declare something even not existing in your project. They are mostly used to resolve cyclic references between classes and to speed up compilation when the complete class declaration is not necessary, and the corresponding #include can be replaced with a forward declaration.
To determine when a forward declaration is sufficient, the sizeof() query can usually answer the question. For example,
class Wheel;
class Car
{
Wheel wheels[4];
};
In this declaration, a forward declaration cannot be used since the compiler cannot determine the size of a Car: it doesn't know how much data the wheels contain. In other words, sizeof(Car) is unknown.
Also regarding templates, forward declared classes cannot be used as template parameters if the template class contains data members of the template parameter (but their pointers can be). For instance,
template<class T> class pointer
{
T *ptr;
};
class Test;
pointer<Test> testpointer;
is legal but
std::vector<Test> testvector will not compile.
Because of the aforementioned limitations, forward declared classes are generally used as pointers or references.
I don't know if there's a book on the subject but you can see this section on c++ faq lite.
Generally speaking you can forward declare in headers as a means of avoiding full includes or as a way to enable circular referencing (bad).
You can use a forward declared type by pointer or reference or return type only.
Large-Scale C++ Software Design by John Lakos (book review here) addresses physical design (files) and logical design and how they relate to software components (which aren't always 1:1 with classes).
if they are in parallel directories you can include it like
#include "../dirB/B.h"
but in header you just call this line for forward decleration
class B;
instead of this, you can seperate your include directories and source directories.
so then you can show include directory as this directory and you can add header by calling
#include "dirB/B.h"
since you will make a forward decleration on header, it wont be problem.
Related
I've gotten into a bit of a design block in a C++ program of mine as two different header files are required to reference each other. Typically a forward declaration would be used here, but since both classes use template functions/constructors a forward declaration cannot be used as methods/variables from both classes need to be used.
For example consider the following scenario (this is pseudo code as an example, it may/may not compile. The objects are representative of my actual application so if a redesign is necessary then I'd love to understand the design philosophies of what I did wrong)
// Application.hpp
#include <Assets.hpp>
#include <Logger.hpp>
class Application {
public:
// Some brilliant code here ...
Logger myLogger;
template <int someArrayLen> Application(std::array<int, someArrayLen> myArr, SomeOtherTypes someOtherStuff) : myLogger(stuffHere) {
mainAssets = new Assets(myArr);
}
~Application(); // Assume this is implemented in Application.cpp and has delete mainAssets;
};
extern Application* mainApp; // Assume Application* mainApp = nullptr; in Application.cpp
// Assets.hpp
// #include <Application.hpp> ???? The issue lies here
class Assets {
private:
// Random data structures/stuff for holding shaders/textures/etc
protected:
template <int someArrayLen> Assets(std::array<int, someArrayLen> myArr) {
if (!shadersSupported()) {
// Main app is an unknown symbol
mainApp->myLogger->error("Your GPU is too old/whatever!");
}
// Random code for loading assets based on my template stuff
}
friend class Application;
public:
// Get assets/whatever here
};
extern Assets* mainAssets; // Assume Assets* mainAssets = nullptr; in Assets.cpp
How can I fix the compile error regarding mainApp being an unknown symbol? Any feedback/help is appreciated, thanks!
I've already looked through all the following questions but none address this unique scenario:
two classes referencing each other
This question had no use of templates so forward declarations could be used as the method bodies weren't defined in the headers
Two classes referencing each other with hash template specialization
The solution from this question cannot be used as here the compiler was unable to figure out how much memory to allocate, whereas in my question the issue isn't regarding the compiler being confused with how much to allocate but rather what to reference
Two template classes being composed of a member of each other
This question addressed a design flaw of circular dependencies which my application does not have, both classes are stored globally, they are just instantiated in separate constructors which reference each other.
Two classes that refer to each other
This question provides forward declarations as a solution which cannot be used here due to the requirement for using the class methods/constructors in template function definitions.
I've also already considered the following:
Trying to change from std::array to pointers, this wouldn't work as my Assets constructor does rely on the lengths of the array.
Trying to change from std::array to std::vector, I want to stick to aggregate initialization so it can be done at compile time, I believe vectors/lists would be too heavy for this.
Forward declarations will indeed work for your problem. The key is that function templates can be defined out of line (i.e., not in your class ... { }; declaration) legally. The same can be achieved for arbitrary functions using the inline keyword.
To now solve your specific problem, just split Application.hpp into Applicaton_fwd.hpp and Application.hpp - similar to iosfwd. Application_fwd.hpp contains almost all the code and Application.hpp includes Application_fwd.hpp and Assets.hpp before defining the Application::Application function template (just like you would define a function in a *.cpp file).
In Assets.hpp, you can simply use Application_fwd.hpp as long as you do not use the constructor. If you also use the Application constructor in Assets.hpp, things become a bit more complicated in that you need to very carefully consider all possible inclusion scenarios (i.e., what happens exactly every time one of your headers is included by themselves or a user) to make sure that it resolves in the order that you need it to without the guards causing trouble.
You can see it in action here
For every pointer p1 of class class1, are there any risks we should consider by using a forward declaration of class1 instead of including class1 header file?
I can see only the advantage: The header file will have less size.
Forward declarations outside the control of the provider of the class are problematic! I’m working on a code base where a lot of forward declarations are used. While things are initially great the existence of forward declarations become a legacy:
Classes can’t be moved from one namespace to a different one. Without the forward declarations the name in the original namespace could be made an alias (typedef or using alias).
Classes can’t be turned into specialisations of class templates as is, e.g., useful when generalising a successful class.
Class templates cannot be forward declared by users as only the first declaration of a class template can provide default arguments.
Assuming the forward declarations are provided via a header under the control of the class provider/implementer (e.g., the implemented providing something akin to <iosfwd>) these problems are not relevant as there is a central place where the declarations can be changed. However, having users decide to declare entities becomes a legacy causing significant cost.
The approach to provision of declarations outlined above seems to have caused some confusion. I'll try to clarify. In my mind the unit of implementation is a component (which is based on John Lakos's notation of a component). A component defines one or more closely related classes and/or functions. The implementation of a component consists of multiple files:
A header file declaring all relevant entities which also defines entities which must be defined when using the component, i.e., user-accessible classes, enumerations, etc. are defined.
A header file only declaring relevant entities provided by the component (multiple related components may share one such header file; <iosfwd> is an example of such a header shared across multiple components).
An implementation file defining all entities [which are meant to be ODR-used] which are only declared in by the headers above.
At least one file with a test driver testing all entities defined by the component.
Users of a component which in some contexts only need to know about names in the component would include the declaration-only header. In no case would a user provide a declaration of a name in a component: all declaration of a name in a component are the responsibility of the provider/implementer of the component.
I can see only the advantage: The header file will have less size.
That's not exactly the point.
Let's assume you have a class declaration in a header file like
namespace MyNamespace {
class Baz;
}
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
and the definition in a separate translation unit as
#include "Baz.hpp"
void Foo::bar(const MyNamespace::Baz & x) {
// actually do something with Baz
}
and in contrast having everything included in the header file (and necessarily all dependent sources will be recompiled when Baz.hpp will be changed)
#include "Baz.hpp"
class Foo {
public:
void bar(const MyNamespace::Baz & x);
};
with the declaration, the 1st version might help to compile the code a little bit faster.
Especially if you have your own headers and class declarations, and if any of these are likely to be changed, you only want to recompile your translation units in the codebase, and not every source file that includes your type dependent header.
Note that forward declarations can be only used with references and pointers. Also header inlined code which dereferences to the forwarded type members cannot be used.
This question already has answers here:
Resolve build errors due to circular dependency amongst classes
(12 answers)
Closed 9 years ago.
Do you have any good advice on how to avoid circular dependencies of header files, please?
Of course, from the beginning, I try to design the project as transparent as possible. However, as more and more features and classes are added, and the project gets less transparent, circular dependencies start happening.
Are there any general, verified, and working rules? Thanks.
If you have circular dependency then you doing something wrong.
As for example:
foo.h
-----
class foo {
public:
bar b;
};
bar.h
-----
class bar {
public:
foo f;
};
Is illegal you probably want:
foo.h
-----
class bar; // forward declaration
class foo {
...
bar *b;
...
};
bar.h
-----
class foo; // forward declaration
class bar {
...
foo *f;
...
};
And this is ok.
General rules:
Make sure each header can be included on its own.
If you can use forward declarations use them!
Use forward declarations where possible.
Move any header includes out of a header file and into the corresponding cpp file if they are only needed by the cpp file. Easiest way to enforce this is to make the #include "myclass.h" the first include in myclass.cpp.
Introducing interfaces at the point of interaction between separate classes can help reduce dependencies.
Some best practices I follow to avoid circular dependencies are,
Stick to OOAD principles. Don't include a header file, unless the class included is in composition relationship with the current class. Use forward declaration instead.
Design abstract classes to act as interfaces for two classes. Make the interaction of the classes through that interface.
A general approach is to factor out the commonalities into a third header file which is then referenced by the two original header files.
See also Circular Dependency Best Practice
depending on your preprocessor capabilities:
#pragma once
or
#ifndef MY_HEADER_H
#define MY_HEADER_H
your header file
#endif
If you find it very boring to design header files maybe makeheaders from Hwaci (designers of SQLite and fossil DVCS) could be of interest for you.
What you're aiming at is a layered approach. You can define layers where modules can depend on lower layer modules but the inverse should be done with observers. Now you can still define how fine-grained your layers should be and whether you accept circular dependency within layers, but in this case I would use this.
In general header files should forwardly declare rather than include other headers wherever possible.
Also ensure you stick to one class per header.
Then you almost certainly will not go wrong.
The worst coupling usually comes from bloated template code. Because you have to include the definition inside the header, it often leads to all kinds headers having to be included, and then the class that uses the template includes the template header, including a load of other stuff.
For this reason, I would generally say: be careful with templates! Ideally a template should not have to include anything in its implementation code.
Altough Artyom provided best answer this tutorial is also great and provides some extenstions http://www.cplusplus.com/forum/articles/10627/
I've recently run into the idea of forward declarations within C++. I have read that by using forward declarations, compile times can be quickened by avoiding unnecessary declarations and recursive #includes. However, this has got me wondering, why exactly does anyone use #includes then?
Are there situations where plain forward declarations just aren't reasonable? Such as if you have a library header file, it would just make more sense to have a single #include then naming each class/function prototype?
I've read many posts on stack overflow explaining the differences between each path, but why exactly use #includes?
The main reason for including headers, rather than using forward declarations throughout your code, is enforcing consistency with minimal duplication.
Consider a header used in several cpp files. When a class or a variable changes in the header, you would need to find and change all references in all files. Otherwise, the code would continue compiling, but it would fail to link.
In addition, forward declarations have their limits: they let you declare pointer to classes or call functions, but they do not allow creating instances or accessing their members.
It is simply that forward declarations you have in mind cannot replace declarations in headers.
One obvious example is the declaration of class:
Assuming I have a Foo class and is going to contains Bar:
This will work
// FOO.H
class Bar;
class Foo {
private:
Bar* bar;
};
But this won't:
// FOO.H
class Bar;
class Foo {
private:
Bar bar;
};
There is a lot of cases that compiler needs to know the "full" declaration (which we usually put in headers) in order to do its work, instead of just a forward declaration containing the name of class etc (which allow you to mostly create pointer/reference to such class).
I'm creating a class called ImageLoader that will be used to load various image formats. For various image formats there are certain structs used. For example with bmp files you have a BITMAPFILEHEADER struct and two others.
What I want to know is, when I'm putting my class definition in the header file, do I make the struct typedefs part of the class definition, or should they be separate, outside the class definition?
I'm not sure because if I was just declaring a struct variable, that would obviously happen in the class, but because I'm defining a type, I'm not sure if it's considered good design to define a type inside a class.
My general rule is that if it will only be used in conjunction with that class, then declare it inside (it implies ownership); otherwise declare it separately.
You get better encapsulation if you leave out everything from the header that you possibly can. Even if some methods of your class need parameters or return types of the struct, you might get away with a forward declaration.
The only time you need to put it in the header is when it's part of the public interface.
As to whether it goes in the class or not, consider whether it's useful on its own or if it is totally subservient to the class. If it can stand alone it should probably go in its own header.
I would not say that declaring a type in a class is an indicator of bad design. Assuming that your mention of "design" means something along the lines of "readability", I would be a stickler for consistency and insist that the same relationships be expressed in the same way.
Otherwise, you are not going to be struck down by a divine wrath for nesting types (Considering SGI is not a smoldering crater). This is pretty context-centric, so there are no hard and fast rules outside of what you define based on your requirements.
If client accessibility is not an issue, I declare most everything in an appropriate scope in headers and just document what my code means. Again, this is if I do not have strict usage/readability guidelines to enforce. I'd go with Mark's suggestion if I did.
Two cents: You could try enumerating image types and using one public struct for config data so that you could justify pulling everything else behind closed doors.
BITMAPFILEHEADER is a structure defined in the Win32 Platform SDK. I'm not sure I've understood your request about it and your class...
In general, if you are defining structures that are not exposed to the client of your class, I'd define them in the private part of your class, or in a sub-namespace Details in your header file, e.g.:
namespace YourCoolLibrary
{
namespace Details
{
struct SomeInternalStructure
{
...
};
} // namespace Details
class YourCoolClass
{
...
private:
Details::SomeInternalStructure m_something;
};
} // namespace YourCoolLibrary
There are even many more choices. If you put it in the class you have to choose if it's public, protected, or private making the class definition visible for every user of the class, only derived classes or no other classes.
If you do not need the details of the class definition I'd put only forward declarations into ImageLoader to keep it simpler. The full definition of the inner class then goes into the implementation file.
My rule of thumb is to make names as local as possible, so if I use it accidentally at the wrong place the compiler will complain.
If the typedef logically belongs into the class you are creating, put it inside; if it would make sense on a global level, leave it outside.