C++ include header file - c++

So, I'm having a problem where:
class A needs to know about class B, class B needs to know about C, and class C needs to know about A.
It's essentially a circle, so I get definition errors. I tried forward declaration, but whatever's on top, doesn't know about what else goes on at the bottom.
How would I go about a situation like this?
Thanks
David

Assuming this is something simple, the comment above by Adam Mihalcin is correct in that the similar question answers it. But I'll code it out anyways.
Assuming you have this (method definitions don't matter) :
class A
{
B* ptrB;
}
class B
{
C* ptrC;
}
class C
{
A* ptrA;
}
Then you can, as Adam linked to, just forward-delcare all 3 of them like this:
class A;
class B;
class C;
And put that block above all 3 of them. The important thing here though is that this is when there are pointers to the other classes, not composition where they're a part of the class. You can use forward-declaration to allow things to compile correctly when dealing with pointers, but not with other data types. So if there was this:
class D
{
B myB;
}
With everything else the same as above, you'd need to have the "real" definition for B above the "real" definition for D. But the rest could be the same. Forward declaration only "works" for pointers.
You MUST break your dependency loop somewhere with a pointer though. If there's never a pointer, then the data structure is "infinite" and thus doesn't work. That's because in my example, a D always contains a B. But what if an A always contained a B, and a B always contained a C, and a C always contained an A? Well that final A needs another B, which needs another C, which... I hope you get the idea. But with pointers, you can loop it. With composition (not pointers) it can't loop around.

If the classes are tightly coupled, then you can do with
Declare the classes with no method implementations, possibly using forward declarations, then implement the methods (possibly in an implementation file).
Otherwise, you can
Factor out the more abstract interface(s) sufficient for the classes to work without knowing full details about each other.
But most probably you have a design level error, and if so, just fix that.

What you can do is forward declare class A in in the header file for class C, then you in the .cpp file, you include the header for class A.
For a reference on how to forward declare class A, take a look at this reference - Forward declarations in C++

most probably, u've just got an design level error.
However, if u have to do this, for example , just try to utilize forward-declare by declaring an empty class A,B without presenting any detail implementation in C's header file. then include A and B's header in C's implementation file when u need to use them.
Remember, u can only use pointer in the declaration of class C.

In your header files use next construction:
#ifndef MYCLASS_HPP__20120410__0747
#define MYCLASS_HPP__20120410__0747
// Your definions of class, struct, etc...
#endif//
And all included file (except self Myclass.hpp) should be in class-header file Myclass.hpp. He must be included in Myclass.cpp file.

Related

Class Inside a Class in C++: Is that heavy?

Suppose I do something like:
class A
{
public:
class B
{
public:
void SomeFunction1() const;
using atype = A;
};
using btype = B;
void SomeFunction2() const;
private:
B b;
};
Then I create an instance of class A and copy it:
A a;
A acopy = a;
Does that make the class A heavy, what I mean is, what happens in the background? I would hope that C++ doesn't really literally "consider" the definition of class B everytime I declare an instance of class A, I thin what happens in the background is that class B will be treated as a new definition under a namespace named A, so A::B is defined. My question is does defining a class inside a class (B inside A) create any overhead when declaring or copying the class A, or it's treated exactly as if B is defined outside?
Thank you everyone :)
Both possibilities (B as nested class and B as external class) will yield exactly the same performance.
In fact, the compiler will generate the same assembly code in both cases.
B as external class:
https://godbolt.org/z/7voYGd6Mf
B as nested class:
https://godbolt.org/z/731dPdrqo
B is a member of A. Hence it resides in A's memory layout and B's constructor will be called every time you constructor/copy A.
The introduced overhead depends on B implementation, but it will be identical in both cases (B nested and external class),
My own opinion is:
It's heavy to read, even with source code folding.
It's often useless: B class could be fully merged with A class most of the time.
Even if B if required by A, and never ever used elsewhere, it can be defined out of A. Constructors are your friends to "force" some associations - delete the default constructor, for example.
Inside or outside A, it doesn't change anything regarding deep copy.
If you need to expose B directly through A, it's a design flaw - move these functions from B to A instead.
So I really don't see, apart "sparing" a header file, what you can "gain" by declaring a class within a class...
For my part, I would prefer:
Use the PIMPL idiom to "hide" B, if it isn't required publicly.
Move everything that needs to be exposed publicly in A either permanently (move the source code), or use wrappers to the PIMPL object.
If you need to replace/share a B instance, change the unique_ptr for the PIMPL object to a shared_ptr instead. Take care of deep copy.
It's usually WAY more efficient, hides perfectly the B code if required (don't even need to export it from a DLL, for example), you won't recompile B at all when changing A and you can change how B work without even breaking your A API.
C++ is a compiled language. We generally assume that the computers used to compile C++ source code are powerful enough. Compilers may reasonable use Gigabytes in the process of compiling an executable.
So when we say that something is "heavy", we usually mean that it's heavy at runtime. The runtime environment for a C++ program may well be a coffee maker or a fridge.
Things like name lookup in nested scopes are pure compile-time actions, and do not have any runtime impact. And modern compilers are smart enough to inline the default methods here, so there's no runtime overhead in calling members.
So I am the one asking the question, I have tested what #david dragilev implemented on Google Benchmark. Results attached, indeed the difference is very small. I can't say the outside version is faster but it theoritically (based on the numbers) is.
Results: https://quick-bench.com/q/sgwCs8kHfePvAaFeLe03uqmCsIo

C++ Declaration of class variables in header or .cpp?

So far, I've been using classes the following way:
GameEngine.h declares the class as follows
class GameEngine {
public:
// Declaration of constructor and public methods
private:
InputManager inputManager;
int a, b, c;
// Declaration of private methods
};
My GameEngine.cpp files then just implement the methods
#include "____.h"
GameEngine::GameEngine() {
}
void GameEngine::run() {
// stuff
}
However, I've recently read that variable declarations are not supposed to be in the header file. In the above example, that would be an inputManager and a, b, c.
Now, I've been searching for where to put the variable declarations, the closest answer I found was this: Variable declaration in a header file
However, I'm not sure if the use of extern would make sense here; I just declare private variables that will only be used in an instance of the class itself. Are my variable declarations in the header files fine? Or should I put them elsewhere? If I should put them in the cpp file, do they go directly under the #include?
Don't confuse a type's members with variables. A class/struct definition is merely describing what constitutes a type, without actually declaring the existence of any variables, anything to be constructed on memory, anything addressable.
In the traditional sense, modern class design practices recommend you pretend they are "black boxes": stuff goes in, they can perform certain tasks, maybe output some other info. We do this with class methods all the time, briefly describing their signature on the .h/.hpp/.hxx file and hiding the implementation details in the .cpp/.cc/.cxx file.
While the same philosophy can be applied to members, the current state of C++, how translation units are compiled individually make this way harder to implement. There's certainly nothing "out of the box" that helps you here. The basic, fundamental problem is that for almost anything to use your class, it kind of needs to know the size in bytes, and this is something constrained by the member fields and the order of declaration. Even if they're private and nothing outside the scope of the type should be able to manipulate them, they still need to briefly know what they are.
If you actually want to hide this information to outsiders, certain idioms such as PImpl and inlined PImpl can help. But I'd recommend you don't go this way unless you're actually:
Writing a library with a semi-stable ABI, even if you make tons of changes.
Need to hide non-portable, platform-specific code.
Need to reduce pre-processor times due to an abundance of includes.
Need to reduce compile times directly impacted by this exposure of information.
What the guideline is actually talking about is to never declare global variables in headers. Any translation unit that takes advantage of your header, even if indirectly, will end up declaring its own global variable as per header instructions. Everything will compile just fine when examined individually, but the linker will complain that you have more than one definition for the same thing (which is a big no-no in C++)
If you need to reserve memory / construct something and bind it to a variable's name, always try to make that happen in the source file(s).
Class member variables must be declared in the class definition, which is usually in a header file. This should be done without any extern keywords, completely normally, like you have been doing so far.
Only variables that are not class members and that need to be declared in a header file should be declared extern.
As a general rule:
Variables that are to be used with many functions in the same class go in the class declaration.
Temporary variables for individual functions go in the functions themselves.
It seems that InputManager inputManager; belongs in the class header.
int a, b, c; is harder to know from here. What are they used for? They look like temporary variables that would be better off in the function(s) they're used in, but I can't say for sure without proper context.
extern has no use here.

C++ and UML diagrams

Let be A and B class such that are which inherit of C class. All are in a file.cpp together with method main of the Main class. If I want create a instance of the classe A then ...
file.cpp
class C{
}
class A : public C{
}
class B : public C{
}
class Main{
.
.
.
void main(){
C *c = new A();
}
}
Where a diagram UML is
Now, Suppose I have the same classes but each class in a different file. If I want to instantiate the class A, as above, I would have insert an #include A.h directive in the Main class which would bring up a dependency in my diagram:
My question is: Which case is correct if I wanted to do the same? or I am interpreting wrong the relations UML in C++?
First off, you should not put code in .h files unless you know what you are doing (see inline functions, mainly used for speed)
Then in main.h, you don't need any reference to A. In main.cpp however, you will need to include A.h. Remember that UML is language agnostic, it is used to draw "who talks to who" rather than "who compiles with who".
More often than not, your c++ compiler will generate an output file (with gcc these are .o files, Visual Studio also does this but transparently) for each cpp file. All output files will then be merged together (most of the time) in your application or library and only then will your function be linked together.
You might also want to take a look at forward references. It is to tell the compiler (not the linker) that "this class does exist, you might not know about it right now, but I swear to God, it WILL exist in the linker output blob".
In your particular case, I would draw the class diagram like your second example, regardless of whether you use only one or multiple cpp files. Your Main class DOES know about A.
Now imagine that your C class have methods like
A* C::createA()
{
return new A;
}
B* C::createB()
{
return new B;
}
Then your main class would have
int main()
{
C* instance1 = C::createA();
C* instance2 = C::createB();
}
In that case, your main class would lose all intimate knowledge of A and B, conforming to your first diagram. This would of course create more coupling between A, B and C, which brings its own problems but is closer to a factory pattern
I don't think its required to have the has-a relationships as in the second diagram because it is implied.
A is-a a C, B is-a C and Main has-a C.
Its more about the structure of your design than the includes in your files.
You need to use the composition relationship to show that Main has-a instance of C.
I have never documented which files need to be included, as it is assumed that if you need functionality of a class that lives in another file, you're probably going to need an include.
EDIT: Actually, there is no composition, as it seems you Main class has a methods called main() that creates an instance of the C class, and is not a member itself.

Understanding of the objects creation in c++

If i have a class name app and a class name manager. I want to create inside manager class an app class, I've seen two options but I didn't understand the difference.
choice 1:
//.....
class app; //writing this line outside the declaration of the func
class manager{
//..
private:
app *a;
//...
}
or choice 2:
class manager{
//..
private:
app *a;
//..
}
I think you're talking about forward declaration. If so, then read this:
C++ INCLUDE Rule : Use forward declaration when possible
Read also this FAQ:
[39.12] What special considerations are needed when forward declarations are used with member objects?
The class app; outside your class manager { ... } is a forward declaration. It tells the compiler, "app is a class. I'm not going to tell you what it looks like, but trust me, it is."
Think of your compiler as only knowing about this particular file (which I am assuming is a .h file) when it compiles. You have said that your member class includes a pointer to an "app". "What the heck is an app?" the compiler wants to know. Without the forward declaration (or perhaps an #include app.h or something similar), it doesn't know, and will fail to compile. By saying at the top, class app;, it knows that app is a class. That's all it needs to know to allocate the space for a pointer to it in your member class.
Look, your "choice 2" isn't valid C++. Who knows what was on your mind... Maybe you wanted to write something like this:
class manager {
//..
private:
class app *a;
//..
}
In this case we define pointer to app class, which is unknown here. This can be used instead of #include "app.h", because all pointers are of the same size and you can define a pointer without defining that app class. Your first example does the same thing, but allows you to omit class word in all subsequent definitions of pointers to it.
The first example includes a forward declaration of the class app so that you can declare pointers to it in later code. The second example doesn't mention app at all before you attempt to use it, so the compiler will not accept it. The compiler needs to know what the name app refers to before you can use it to declare additional things.
Since you're only declaring a pointer, you don't yet need to have a full declaration of app. But in order for your program to fully compile and link, you'll need to define app eventually. Possibly within the same file, or possibly in some other file. But somewhere before you attempt to create an instance of that class or use any of its member variables and functions.

A few questions about C++ classes

I have two basic questions. The first one is about function in other classes. If I have a header file with a class in it and I want to use that function in another class I have created, do I always have to construct a class object to run a function in that class like:
someclass class; <----object construction
class.somefunction();
Is there a way just to call the function with the object construction?
And the second question is it okay to put multiple small classes in one header file?
Functions should only be member functions if they act on an object of the class. Functions that don't act on an object should just be plain global functions (or class static):
// Global function
void foo() { /* do something */ }
// Static function
class Foo
{
public:
static void foo() { /* do something */ }
};
For your second question, yes it's ok. Generally people stick to one class per file, but in my opinion there's nothing wrong with having a few small classes in a single file.
If your function is declared static then you don't need an object instance to call it.
class Foo
{
public:
static void Bar() {}
};
// ...later
Foo::Bar();
To answer your second question, yes it's sometimes ok. I've done that before with small utility structs that are related to each other. Usually I'm just being lazy and don't want to bother making separate files.
Is there a way just to call the function with the object construction?
Only if the function is declared static. (ok, that's a lie, its possible without constucting a object if you subvert the type system, but it's not a good idea)
And the second question is it okay to put multiple small classes in one header file?
Sure, it's done all of the time.
1 static as already mentioned
2 do what feels natural. Keep related classes together. One of the problems with JAva is its fanatical enforcement of one class per file
However - unforgivable sin is spreading the implementation of class a throughout the implementations of classes b c and d
Ie all of a class implementation should be in one .cpp file.
delcare the function as static.
Are you talking about inner classes? If thats the case, then its totally legit.