Having trouble to understand circular declaration - c++

Hi i'm trying to create a factory method, that returns a derived class of class A, I'm having trouble understanding circular declaration, I hope you can help me solve this.
Thanks.
AChildOne.cpp
#include "AChildOne.h"
AChildOne.h
#ifndef ACHILDONE_H
#define ACHILDONE_H
#include "A.h"
class A_CHILD_ONE : public A {
};
#endif
A.cpp
#include "A.h"
void A::a(){
Factory::fact();
};
A.h
#ifndef A_H
#define A_H
#include "Factory.h"
class A {
public:
static void a();
};
#endif
Factory.cpp
#include "Factory.h"
A *Factory::fact(){
return new A_CHILD_ONE;
}
Factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include "A.h"
#include "AChildOne.h"
class Factory {
public:
static A *fact();
};
#endif
Compilation error
g++ A.cpp Factory.cpp AChildOne.cpp -o test
In file included from Factory.h:5:0,
from A.h:4,
from A.cpp:1:
AChildOne.h:5:30: error: expected class-name before ‘{’ token
class A_CHILD_ONE : public A {
^
In file included from A.h:4:0,
from A.cpp:1:
Factory.h:9:10: error: ‘A’ does not name a type
static A *fact();
^
A.cpp: In static member function ‘static void A::a()’:
A.cpp:4:2: error: ‘fact’ is not a member of ‘Factory’
Factory::fact();
^
In file included from A.h:4:0,
from AChildOne.h:3,
from AChildOne.cpp:1:
Factory.h:9:10: error: ‘A’ does not name a type
static A *fact();
^

In Factory.h you try to include A.h; in A.h you try to include Factory.h.
Including Factory.h into A.cpp and removing from A.h should help.
Factory declaration depends on A interface. A declaration doesn't depend on Factory declaration but A definition does.
Also, Factory.h doesn't need to know about AChildOne.h but Factory.cpp does. So move #include AChildOne.h to Factory.cpp.

Related

error: member access into incomplete type''; note: forward declaration of ''

Here is a struct MAIN which have member struct A and struct B, the code is like below
// a.hpp
#ifndef _A_HPP_
#define _A_HPP_
struct A
{
int mem1;
};
#endif
// b.hpp
#ifndef _B_HPP_
#define _B_HPP_
#include "a.hpp"
#include "main.hpp"
struct MAIN;
struct A;
struct B{
int mem2;
MAIN* main;
A *aptr;
B(){
*aptr=this->main->a;
}
};
#endif
// main.hpp
#ifndef _MAIN_HPP_
#define _MAIN_HPP_
#include "a.hpp"
#include "b.hpp"
struct MAIN{
A a;
B b;
};
#endif
// main.cpp
#include "main.hpp"
int main(){
MAIN m;
return 0;
}
I'd like to use the aptr in struct B to visit A which in the same MAIN, but compile error like
In file included from main.cpp:2:
In file included from ./main.hpp:6:
./b.hpp:15:25: error: member access into incomplete type 'MAIN'
*aptr=this->main->a;
^
./b.hpp:7:8: note: forward declaration of 'MAIN'
struct MAIN;
^
1 error generated.
How the error occured? my code should use struct but not class, and hpp but not h with cpp. Is there anyway to fix it? Hope for help
The definition of the constructor B::B inside the struct definition references members of MAIN, but the latter hasn't been fully defined yet.
You need to move the body of constructor B::B into a separate file, i.e. b.cpp, and link with main.cpp when building the executable.

Circular Inclusion Error, Template source files

I have two non-template classes, A and A::nested, and a class template, B.
I have a problem where a templated method in class A (A_method), defined in a .tpp file (A.tpp), requires the definition of class B since it tries to modify a member of class B inside it.
At the same time, a method in class B requires the definition of class A since one of its parameters is a class nested inside class A (A::nested).
The specific error is:
error: invalid use of incomplete type 'class B<>'
I have traced this problem to have arisen from the compilation of B.cpp, where it then #includes B.hpp, which #includes A.hpp, which #includes A.tpp, which #includes B.hpp again.
I have included the files below, they are all short and below 30 lines. Thank you.
types.hpp (just an empty class holder for significance)
#ifndef TYPES
#define TYPES
class defaulttype {};
class argtype {};
class alttype {};
#endif // TYPES
A.hpp
#ifndef A_HEADER
#define A_HEADER
#include "types.hpp"
template<typename = defaulttype>
class B;
class A
{
public:
template<typename...>
class nested{};
B<>* data_member;
B<alttype>* const second_data_member;
template<typename Type>
void A_method(B<Type>);
A();
};
#include "A.tpp" //".tpp" is the extension I am using to indicate
//template source files, other places may use ".tcc" or ".ipp"
#endif //A_HEADER
A.tpp
#ifndef A_TPP
#define A_TPP
#include "B.hpp"
#include <iostream>
template<typename T>
void A::A_method(B<T> object)
{
data_member->next = &object;
std::cout << object.name;
}
#endif // A_TPP
A.cpp
#include "A.hpp"
A::A()
:second_data_member(new B<alttype>)
{}
B.hpp
#ifndef B_HEADER
#define B_HEADER
#include "A.hpp"
#include "types.hpp"
#include <iostream>
//default arg is defaulttype, previously forward declared as such in A.hpp
template<typename T>
class B
{
public:
B* next;
};
template<>
class B<argtype> : public B<>
{
public:
std::string name;
template<typename...argpack>
void B_func_requires_nested(A::nested<argpack...>);
};
#include "B.tpp"
#endif //B_HEADER
B.tpp
#ifndef B_TPP
#define B_TPP
template<typename...argpack>
void B<argtype>::B_func_requires_nested(A::nested<argpack...> object)
{}
#endif // B_TPP
B.cpp
#include "B.hpp"
Thank you for the help.

Invoke a base class constructor from the other module

Let I've two .cpp files: a.cpp and b.cpp which contains classes defenition as the following:
//a.cpp
class A
{
public:
A(){ \\some actions }
}
//b.cpp
class A;
class B : A
{
public:
B():A(){ \\some actions }
}
But during the compile time I've an error. The error's description is:
ConcreteSubject.cpp:5:25: error: invalid use of incomplete type ‘class
Subject’ ConcreteSubject.cpp:3:7: error: forward declaration of ‘class
Subject’ ConcreteSubject.cpp: In constructor
‘ConcreteSubject::ConcreteSubject()’: ConcreteSubject.cpp:21:38:
error: type ‘Subject’ is not a direct base of ‘ConcreteSubject’
Is it possible to avoid #include "a.cpp"?
You should move class declaration of A to a header file and include that header file in you b.cpp file. If you don't do this, b.cpp compilation unit has no way to know the list of constructors implemented (explicitly or implicitly) by classs A.
Including a cpp file is not a good idea. You should not do this.
//a.h
class A
{
public:
A();
}
//a.cpp
A::A(){ \\some actions }
//b.cpp
#include "a.h"
class B : A
{
public:
B():A(){ \\some actions }
}

Forward declaration VS compiling order error in c++ to avoid recursive header inclusion

I'm working on a large code in c++ composed by a lot of .h and .c files.
The main problem is caused by a pair of class wich are supposed to link each other.
Due to declaration need in the software architecture, the first class (name it A) is initializated in an "upper level" class.
so we got something like:
#include A.h
class mainClass{
...
A a;
...
}
A.h looks like:
#ifndef A_H
#define A_H
#include B.h
class A{
A();
fooA();
...
private:
B b;
...
}
#endif
A.cpp looks like:
#include B.h
#include A.h
...
A::A(){
...
b(this) //here I get the first error that follows
...
}
A::fooA(){//do somthing}
In order to avoid mutual header inclusion in the second class (let it be B) I used forward declaration and a pointer var to class A.
B.h looks like:
#ifndef B_H
#define B_H
class A; //Forward declaration to A
class B{
B()
B(A* const t)
fooB();
A* a; //pointer to A object
}
B.cpp looks like:
#include B.h
B::B(){
//default constructor. Do Nothing
}
B::B(A* const t){
this->a=t //constructor that set the pointer to the object of type A
}
B::fooB(){
a->fooA(); //here i get the second error that follows
}
Now if in my Makefile I link A before B i get the compiling error:
//First error. See code above for line numbers
error: no match for call to ‘(B) (A* const)’
On the other hand if I link B before A i get the compiling error:
//Second error. see code above for line numbers
error: invalid use of incomplete type ‘struct A’
_B.h:'line of the forward declaration': error: forward declaration of ‘struct A’
I must admint i'm pretty new to c++ so I can't understand where I'm wrong.
EDIT
Now I'm using the solution:
use include guard
forward declare class A, and don't include A.h in B.h
include both B.h and A.h in A.cpp and B.cpp. Always include B.h before A.h
but I get the same error:
error: no match for call to ‘(B) (A* const)'
Could it be a constructor Overloading problem? If I remove the line
b(this)
The compiling works fine.
SOLVED
If a use an help function that set the variable A* a in B insted of using a constructor Everything works fine during compilation. Maybe I need to better understand constructor overloading in C++. Thank you very much.
use include guard
forward declare class A, and don't include A.h in B.h
include both B.h and A.h in A.cpp and B.cpp. Always include B.h before A.h
Try including "A.h" from B.cpp!
That will resolve your "A" type when you need to use A from B.cpp. Just make sure you don't do anything but keep a pointer/reference to A from within B.h, and do all real work with A from within B.cpp.
First of all - follow 'us2012' idea and use include guards!
Then - change the forward declarations:
A.h:
#ifndef A_H
#define A_H
class B;
class A{
A();
fooA();
...
private:
B b;
...
}
#endif
and the include B.h in A.cpp
in B.h you include again A.h - but the include guards should prevent errors:
#ifndef B_H
#define B_H
#include "A.h"
class B{
B()
B(A* const t)
fooB();
A* a; //pointer to A object
}
#endif
I haven't tested it ... but it should work.

C++ Tricky Inheritance Class Definition Problem

I'm getting this error when dealing with a number of classes including each other:
error: expected class-name before '{' token
I see what is going on, but I do not know how to properly correct it. Here is an abstracted version of the code:
A.h
#ifndef A_H_
#define A_H_
#include "K.h"
class A
{
public:
A();
};
#endif /*A_H_*/
A.cpp
#include "A.h"
A::A() {}
B.h
#ifndef B_H_
#define B_H_
#include "A.h"
class B : public A
{ // error: expected class-name before '{' token
public:
B();
};
#endif /*B_H_*/
B.cpp
#include "B.h"
B::B() : A() {}
J.h
#ifndef J_H_
#define J_H_
#include "B.h"
class J
{
public:
J();
};
#endif /*J_H_*/
J.cpp
#include "J.h"
J::J() {}
K.h
#ifndef K_H_
#define K_H_
#include "J.h"
class K : public J
{ // error: expected class-name before '{' token
public:
K();
};
#endif /*K_H_*/
K.cpp
#include "K.h"
K::K() : J() {}
main.cpp
#include "A.h"
int main()
{
return 0;
}
Starting in main.cpp, I can determine that this is what the compiler sees:
#include "A.h"
#ifndef A_H_
#define A_H_
#include "K.h"
#ifndef K_H_
#define K_H_
#include "J.h"
#ifndef J_H_
#define J_H_
#include "B.h"
#ifndef B_H_
#define B_H_
#include "A.h"
class B : public A
{ // error: expected class-name before '{' token
So, A's definition is not complete when we get to B. I've been told that sometimes you need to use a forward declaration and then move the #include statement into the .cpp file, but I'm not having any luck with that. If I try anything like that, I simply get the additional error:
error: forward declaration of 'struct ClassName'
I think maybe I'm just not doing things in the right places. Can someone please show me how to get this code to compile? Thank you very much!
Edit: I want to point out that this is just abstracted version of the real code. I realize that there are no references to K in A or B in J, but there are in the real code and I feel that they're completely necessary. Perhaps if I give a brief description of the real classes, someone can help me restructure or fix my code.
Class A is an abstract node class that acts as an interface for nodes in a graph. Class B is one of what will be a number of different implementations of A. In the same manner, class J is an abstract Visitor class and K is the corresponding implementation. Here is the code with a little more context:
A.h (Abstract Node)
#ifndef A_H_
#define A_H_
#include "K.h"
class K;
class A
{
public:
A();
virtual void accept(const K&) const = 0;
};
#endif /*A_H_*/
A.cpp
#include "A.h"
A::A() {}
B.h (Concrete Node)
#ifndef B_H_
#define B_H_
#include "A.h"
class K;
class B : public A
{ // error: expected class-name before '{' token
public:
B();
virtual void accept(const K&) const;
};
#endif /*B_H_*/
B.cpp
#include "B.h"
B::B() : A() {}
void B::accept(const K& k) const { k.visit(this); }
J.h (Abstract Visitor)
#ifndef J_H_
#define J_H_
#include "B.h"
class B;
class J
{
public:
J();
virtual void visit(const B*) const = 0;
};
#endif /*J_H_*/
J.cpp
#include "J.h"
J::J() {}
K.h (Concrete Visitor)
#ifndef K_H_
#define K_H_
#include "J.h"
class B;
class K : public J
{ // error: expected class-name before '{' token
public:
K();
virtual void visit(const B*) const;
};
#endif /*K_H_*/
K.cpp
#include "K.h"
K::K() : J() {}
void K::visit(const B*) const {};
main.cpp
#include "A.h"
int main()
{
return 0;
}
I had to add some forward declarations to make some additional errors that appeared (when I added detail) go away. Some of them may not be necessary or correct.
Your header inclusions are circular. A -> K -> J -> B -> A. Using forward declarations is the simplest way to avoid such complexity, but it is only possible when the class being declared only uses references or pointers to the class being included. You can't use forward declaration in K.h or B.h, for example, because they inherit from J and A respectively. However, you may be able to replace the #include "K.h" in A.h with class K; depending on how you are actually using K in A.
Talk about confusing.
In this concrete example, remove the
#include "B.h"
from file J.h since it' s not needed there. If that doesn't work, we would need some more details about how J uses B...
EDIT
Since J only uses a pointer to B, the advice stays the same :-) :
Remove #include "B.h" from J.h and replace it by a forward declaration of B:
(J.h)
class B;
class J
{
// ...
virtual void visit(const B*) const = 0; // This will work with forward declaration
}
Also remove #include "K.h"from A.h.
IMPORTANT
Of course you need to add the needed includes in the respective CPP files:
(J.cpp)
#include "B.h"
// ...
// Go ahead with implementation of J
// ...
(Same for A.cpp, include K.h)
The main problem is that your header files include each other in a circular manner. A includes K which includes J which includes B which then includes A again... You should never require a situation where this happens. You should go back to the design drawing board and either cut some of the dependencies, or reorganize your classes entirely so that this circular dependency doesn't happen.
The problem is that your header files cyclically depend on each other. Don't include K.h in A.h and B.h in J.h. They aren't needed there.
Regarding your edit: this is not the best way for your objects to interact. Rethink your design. Who calls node.accept(visitor)? Can't you call visitor(node) directly?
Also, if you're trying to design a graph library, have a look at Boost.Graph library.
That said, since you only use a pointer to B in J.h, you don't have to include B.h, only forward-declare the class.
class B;
struct J
{
virtual void visit(const B*) const = 0;
};
Then include B.h in your K.cpp file.
#include "K.h"
#include "B.h"
void K::visit(const B* b) const
{
// use b here any way you want
}
Circular inclusions do not work.
Try to keep inclusions to a strict minimum. If you do that, you'll either be fine altogether, or you'll discover problems in your design. In your case, i don't see anything wrong with your design.
When defining class K, you're only using a pointer to an object of type B. That does not require B to be defined (as in "include the header file"), only to be declared (forward declaration is fine). So, in your case, removing inclusion to header "B.h" replaced by "class B;" is sufficient. (the same goes for class J)