about class declaration in header file C++ - c++

Here is the problem. I need to write header file with two classes, say class A and class B.
in class A I have function that uses object of class B and vice versa, i.e. in class B I have function that uses objects of class A.
If A declared first then there would be error that class B has not been declared.
How to deal with it? I try declare function of a class A after declaration of class B:
void classA::myfunc (classB *b);
But I got the error that function myfunc is not declared.
Experienced people in C++, what to do?
Added:
here is a good link about header

If you need a pointer to a class on a header, not the full object, just add a forward declaration, dont include the header of the pointer's class.
I'm sure that you just use pointers to access that classes that one have a reference to another, dont you? You know, because if you use instances, you got a instance looping. Use forward declarations.
Here's a example of how you can use forward declarations:
A.h
class B;
class C;
class D;
class E;
class A {
B* pointer; //To just have a pointer to another object.
void doThings(C* object); //if you just want to tell that a pointer of a object is a param
D* getThings(); //if you wanna tell that a pointer of such class is a return.
E invalid(); //This will cause an error, because you cant use forward declarations for full objects, only pointers. For this, you have to use #include "E.h".
};
To illustrate how can have a class that mentions one that pointers its type:
B.h
class A;
class B {
A* pointer; //That can be done! But if you use a includes instead of the forward declarations, you'll have a include looping, since A includes B, and B includes A.
}
As mentioned by Tony Delroy (Many thanks to him) You should not ALWAYS use this design. It's provided by the C++ compiler, but its not a good practice. The best is to provide reference header, so your code would look like:
A.h
#include "B.fwd.h"
#include "C.fwd.h"
#include "D.fwd.h"
#include "E.fwd.h"
class A {
B* pointer; //To just have a pointer to another object.
void doThings(C* object); //if you just want to tell that a pointer of a object is a param
D* getThings(); //if you wanna tell that a pointer of such class is a return.
E invalid(); //This will cause an error, because you cant use forward declarations for full objects, only pointers. For this, you have to use #include "E.h".
};
and yours forward headers like this:
B.fwd.h:
class B;
In your fwds, you should have your class forward declaration, and any typedefs that comes with it.
I'm not mentioning the #pragma once, or the #ifndef B.H... you know they'll be there :D
Your code would be on a standard defined by <iosfwd> and better to maintain, specially, if they are templates.

Short answer:
class classA;
Then you defined your classB and then the declaration of classA.
This is called forward-declaration, and is there to solve your problem :)

You can try to add a forward declaration of a class before you use it with a ref or ptr.
classA.h:
class classB;
class classA {
void fun(classB * b);
}
classB.h:
class classA;
class classB {
void fun(classA * a);
}
classA.cpp:
#include "classA.h"
#include "classB.h"
...
classB.cpp:
#include "classA.h"
#include "classB.h"
...

Related

How to Foward Declare Classes Across Files C++

I have been trying to figure out how to forward declare classes across multiple files in C++. I was able to successfully do it with two classes, but doing this across many classes puzzled me. I tried forward declaring all the classes in a header file and including that in all the classes, but I got the error of incomplete classes. I looked into it, but all the solutions seemed unreasonable or confused me. Can you please explain a good way to do it.
If it helps here is some example code of the issue that specifically occurring. Class A is included in Class C, but Class A also includes Class B which holds Class C resulting in an error because Class C has not been declared.
Class Forward Declaration
//Tried "Class Name {};" but that also failed
Class A;
Class B;
Class C;
Class A
//Class A
#include "B.h"
class A{
private:
B b;
public:
void SetBInt(int set) {b.SetInt(set);}
}
Class B
//Class B
#include "C.h"
class B{
private:
C c;
int i = 0;
public:
void SetInt(int set){i = set;}
}
Class C
//Class C
#include "A.h"
class C{
private:
int i = 0;
public:
void SetInt(int set){i = set;}
}
You have to avoid circular dependencies. One common way to avoid them is by pre-declaring the type, and not having any instances or function calls of that type in the header.
You do this by changing instances, such as B b, into references or pointers: B* b. You also have to move any code that uses b into the CPP file, so you can #include "B.h" prior to using it.
For example, instead of
// we'll remove this header's dependency on B shortly
#include "B.h"
class A
{
B b;
public:
A() { b.SetInt(0); }
};
You do something like this:
class B;
class A
{
B *b; // *pointers and &references to a predeclared class are fine.
public:
A();
~A();
};
... and then in A.cpp:
#include "A.h" // ALWAYS include your own header first
#include "B.h"
A::A()
{
// we didn't need to know how big B was until now, when we're about to make one and
// run its constructor. We'll also need to know what functions are available, and the
// types of all its parameters (or lack of parameters).
b = new B();
b->SetInt(0);
}
A::~A()
{
delete b; // for every "new" there must be a "delete"
}
Yes, this would be (much) better with std::unique_ptr<B> b instead of a raw pointer. With a smart pointer we wouldn't need an explicit destructor. I just didn't want to throw too much potentially new stuff at someone still learning.
Alternatively, you could pass a reference into the constructor, and use the member initializer list (you can only set references when they're constructed). This raises problems with "Object Lifetime". If the instance of B you pass in at construction time is destructed before A is done with it, you're program will violently crash (if you're lucky: that way you'll have a good idea of what the problem is) the next time it's used. Best to avoid it till you have considerably more experience under your belt.

same #include statements in derived classes

I have two questions
lets say there is a base class and several derived classes, the derived classes are going to have all of the #include statements (like #include <iostream> etc) and using lines of the base class.
1. is it considered a good practice to write the base class's #include statements and using lines in the in the derived classes h. file anyway?
2.same question regarding composition - class A has an object of class B as a member, is it a good practice to writes Bs#include` statements in A's h. file anyway?
thanks!
I think it is a good practice to have each include file actually #include any of the definitions it needs, so that in your main program, you can #include your most deeply derived class without having to have additional #include statements for the definitions that class needs.
You can have class definitions contain pointers to previously undefined classes, as follows:
class forward_ref;
class myClass :
Public:
myClass(){}
forward_ref* ptr_to_forward_ref;
};
lets say there is a base class and several derived classes, the
derived classes are going to have all of the #include statements (like
#include <iostream> etc) and using lines of the base class.
Not at all.
First of all, you are not supposed to put using lines at top-level scope in header files. This is a common beginners' mistake.
Second, what makes you think the derived class needs all #includes of the base class? The derived-class header file needs to include the base-class header file, and the derived-class implementation file needs to include the derived-class header file.
This already gives you all includes.
base.h:
#include <string>
class Base
{
// ...
virtual std::string f(); // no `using`
};
derived.h:
#include "base.h"
// no need for <string> here
class Derived : public Base
{
// ...
virtual std::string f();
};
derived.cpp:
#include "derived.h"
// no need for <string> here
std::string Derived::f() // could have used `using std::string`
{
// ...
}
Now of course, it's technically possible to actually do it otherwise, in a more complicated fashion, like this:
base.h:
// no <string>?!
class Base
{
// ...
virtual std::string f();
};
derived.h:
#include "base.h" // still no <string>?!
class Derived : public Base
{
// ...
virtual std::string f();
};
derived.cpp:
#include <string> // ah, OK
#include "derived.h"
std::string Derived::f()
{
// ...
}
This works only because the compiler doesn't separately compile header files but only compilation units (~= .cpp files) as a whole, after all includes have been processed.
But talk about horrible programming style. Why would you want to force everyone who derives from your class to include extra headers?
2.same question regarding composition - class A has an object of class B as a member, is it a good practice to writes Bs#include` statements
in A's h. file anyway?
It depends. If A's header needs access to any of B's members, then you have to use an include, and in that case, again, you just include what you need in b.h and let a.h #include "b.h".
If A's header only needs a pointer or a reference to B, or just a return value, then you can use a forward declaration in order to potentially speed up compilation. Of course, speeding up compilation is not something a C++ beginner should care about, because a lot of time will pass until you will be developing software which take hours to build :)
Anyway, for completeness' sake:
a.h:
class B; // forward declaration, no #include
class A
{
// ...
B f();
B *ptr;
B &ref;
};
a.cpp:
#include "a.h"
#include "b.h" // need the include here
B A::f()
{
B obj;
return obj;
}
b.h:
class B
{
// ...
};
In answer to question 2: typically you would include class B's header file in A's header file (so all the includes needed for A will automatically be included).
However, as pointed out in Logicrat's answer, you could alternatively include only a pointer to B in A. In this case you can use a forward declaration of B in A.h instead of including B.h. The downside to this is that all functions that need to make use of B must then go in A.cc (which will definitely have to include B.h). The advantage is that you can greatly reduce the quantity of code in the header files (since each #include copies an entire header file into the current file just before compilation), which can speed up compilation times.

Casting between shared_ptr of forward declared class hierarchy

I have a class manipulating only shared_ptr to an inheritance hierarchy (quite simple, there are a few classes, say A, B, C etc. inheriting from a single class Base). Since I do not need to manipulate the instances of A, B, C... themselves, they are only forward declared. However, the compiler chokes when I try to pass a shared_ptr<A> to a method taking a shared_ptr<Base>, since the compiler does not know that A inherits from Base. Is there any other way than either static_pointer_castor #includethe header of class A? And if not, which one would you choose?
EDIT: adding some code
// in some file: (Base.h)
class Base
{
/*code*/
}
// in another file (A.h)
class A : public Base
{
}
// in my file (impl.cpp)
class A; // forward declaration
void Dummy()
{
std::shared_ptr<A> myPtr;
// we have somewhere: void sillyFunction(shared_ptr<Base> foo)
sillyFunction(myPtr); // does not compile, as no conversion is found.
}
Is there any other way than either static_pointer_castor #includethe header of class A?
No. In fact, the #include is the only way to do it properly (static_pointer_cast either wouldn't work or invokes undefined behavior). You can't cast ordinary pointers between incomplete subclass and superclass, either.

C++: How can 2 classes call each other without redeclaration and without headers calling each other

I have a bit of problem with this. I have a class A which instantiates an object of B and then B which instantiates an object of A. Is this at all possible? I tried adding this in the headers of each
#ifndef A
#define A
class a...
#endif
but if keeps me in an infinite header loop which it reaches the maximum header includes, so obviously one is calling the other and the other is calling that one. Is there any way to achieve this?
edit: Okay this seems like a good answer but now A complains that B doesn't have a Constructor despite the fact that it definitely has a constructor. I can't figure that one out.
You can forward declare the classes, for example:
A.h:
class B;
class A
{
B* a_;
};
B.h:
class A;
class B
{
A* a_;
};
In your source files where you actually use the classes (that is, create them, destroy them, use their members, etc.), you will need to include both headers so that their definitions are available:
#include "A.h"
#include "B.h"
You should break this circular dependence. For instance, you could use a pointer to B, and you could then forward declare the B class.
Have you tried using forward declaration?
class B;
class A
{
private:
B* instanceOfB_;
};
This is not a good design to start with. However to make it possible just use forward declaration.
In classA.h file remove any includes to classB.h and move them to the classA.cpp. Then before declaring classA write the line class B; to forward declare class B. This way you can have member variables of B* (but not B) inside class A. Do the same for classB next.
You can forward declare A in B's header file, and the other way around, to achieve what you want.
// In B.h
class A;
class B
{
private:
A a;
};
See Wikipedia for more information.
If you mean class A {B b;}; and class B {A a;}, no you can't. Class data members are included in the class, so you'd have a B that included an A that included a B that included an A.... Remember, in C++ a data object is not a reference to something, but is the actual thing.
You need something like class A {B * b;}; and class B {A * a;}, where you are providing pointers. Before the definitions, you need something like class A; class B; to tell the compiler that A and B are classes. These are called "forward declarations".

Forward declaration of class doesn't seem to work in C++

The follwing code is compiled in VC++6. I don't understand why I am getting the compilation error C2079: 'b' uses undefined class 'B' for the following code.
Class B Source
#include "B.h"
void B::SomeFunction()
{
}
Class B Header
#include "A.h"
struct A;
class B
{
public:
A a;
void SomeFunction();
};
struct A Header
#include "B.h"
class B;
struct A
{
B b;
};
If I changed class B header to the following, then there will be no error. But the header declaration won't be at the top!
Class B Header with weird header declaration
struct A;
class B
{
public:
A a;
void SomeFunction();
};
#include "A.h"
In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I've only ever seen it used for pointers and (less often) references.
Beyond that, what you're trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.
B.cpp
#include "B.h"
void B::SomeFunction()
{
}
B.h
#ifndef __B_h__ // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"
class B
{
public:
A a;
void SomeFunction();
};
#endif // __B_h__
A.h
#ifndef __A_h__ // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"
class B; // forward declaration
struct A
{
B *b; // use a pointer here, not an object
};
#endif // __A_h__
Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level - classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.
class MyClass
{
public: // classes use private visibility by default
int i;
MyClass() : i(13) { }
};
struct MyStruct
{
int i;
MyStruct() : i(13) { }
};
Forward declarations, like
struct A;
or
class A;
Introduce A as an incomplete type and it remains incomplete until end of type's definition is reached. There are things you can do with incomplete types and things you can't. You can
Declare variables (or members) of type "pointer to A" and "reference to A"
Declare functions which take arguments of type A or return type A
You can't
Declare variables (nor members) of type A
Dereference pointers to A or access any members of references to A
Define subclasses of A.
In your code you try to declare struct member of incomplete type. It's illegal. Only pointers and references are allowed.
public:
A a;
You are trying to create the object of A with only forward declaration. Compiler at this moment ( with only forward decl) cannot decide the size of the object A and hence, it cannot allocate memory required for A. So you cannot create objects with only forward decl.
Instead replace with:
A* a;
Pointer or reference to A without A's class definition will work fine.
Two issues jump out at me here.
1: You've written Struct A instead of struct A; note the lower-case "s". Your compiler might consider the equivalent, but I don't think it's standard C++.
You have defined a circular reference between A and B. Each A object must contain a B object, but each B object must contain an A object! This is a contradiction, and will never work the way you want it to. The usual C++ way to solve that problem is to use pointers or references for A::b or B::a (or both).
You alse include A.h from B.h and B.h from A.h. You should at least use preprocessor macros:
#ifndef __A_H__
#define __A_H__
// A.h contents
#endif
so that file won't be included more than once.
If you create an instance of A, that will create an instance of B (member var) which will create an instance of A (member var) which will create an instance of B which will create an instance of A and so on...
The compiler should not allow this since it requires infinite memory.
To solve this, either A or B must use a reference/pointer to the other class.