Can you figure out how to solve this circular inclusion problem?
C extends B and B includes A. A includes C. Every forward declaration I tried hasn't worked.
Errors
Error 1 error C2504: 'B' : base class undefined
Error 2 error C3668: 'C::c' : method with override specifier 'override' did not override any base class methods
File A.h:
#pragma once
#include "C.h"
struct A
{
A();
C c;
};
File B.h:
#pragma once
#include "A.h"
struct A;
struct B
{
virtual void c() = 0;
A* a;
};
File C.h:
#pragma once
#include "B.h"
struct B;
struct C : public B
{
void c() override;
};
The solution is always the same and it looks like you were on the right track. However, you're not using forward declartions correctly. There should be many examples of how to do this for example here.
B.h
// Why are including "A.h" here, this is causing your circular include
// issue, it needs to be moved to your implementation (e.g., "B.cpp")
#include "A.h"
struct A; // Forward declaration, good
struct B
{
virtual void c() = 0;
A* a; // A pointer only requires the above forward declartion
};
C.h
#include "B.h" // Necessary since you're extending `B`
struct B; // This forward declaration is superfluous and should be removed
struct C : public B
{
void c() override;
};
Related
I have 3 classes (A, B & C) in different .h files. How can I move the #includes and forward declarations in order for it to compile.
Currently I've used forward declaration in A.h and thought it would work from there. Instead C.h is throwing many compiler errors of 'class A' is inaccessible with in this context.
// A.h
#pragma once
...
class B;
class A {
private:
B *parent_;
};
// B.h
#pragma once
...
#include <A.h>
class B : A {
public:
virtual void func(A *arg);
};
// C.h
#pragma once
...
#include <A.h>
#include <B.h>
class C : B {
public:
virtual void func(A *arg);
private:
A *left_child;
A *right_child;
};
The name A is private via B. You can either change to public or protected inheritance in B, or use (the fully-qualified name) ::A in C
UPDATE:
Now I have this, and it does not compile:
A.h:
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getfoo();
};
#endif
A.cpp:
#include "A.h"
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
#ifndef B_H
#define B_H
class B {
private:
A myA;
public:
B();
int getAvalue();
};
#endif
B.cpp:
#include "A.h"
#include "B.h"
int B::getAvalue(){
return myA.getfoo();
}
Errors:
b.h line 6: C2146: missing ';' before identifier 'myA'
b.h line 6: C4430: missing type specifier - int assumed
b.h line 6: C4430: missing type specifier - int assumed
END UPDATE
I have written 2 classes in different cpp and header files: class A and class B.
Class B uses class A as a private variable and the default constructor of class A is never called.
Here is my code:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
class B {
public:
int getAvalue();
};
B.cpp:
#include "A.h"
class B {
private:
A myA;
public:
int getAvalue();
};
int B::getAvalue(){
return myA.getfoo();
}
classtest.cpp:
#include "stdafx.h"
#include <iostream>
#include "B.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
B stackB;
cout << stackB.getAvalue() << endl;
B* storeB = new B();
cout << storeB->getAvalue() << endl;
cin.get();
return 0;
}
The output is never 5 and the breakpoint inside the constructor A::A() is never triggered. It doesn't matter if I use B globally or locally. This sample works totally fine if I put the classes and functions in one single file.
If I add an empty default constructor to class B, the default constructor of class A gets called, but then Visual Studio 2008 complains about stack corruption around variable stackB.
What am I doing wrong?
Just with this class alone:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo() {
return foo;
}
You are declaring class A in A.h.
Then in your implementation(cpp) file, you are then again declaring class A.
You are also forgetting to include A.h in A.cpp. If you included the header into the cpp; the compiler would of thrown out errors telling you what was wrong. You are also missing either header guards, or the pragma directive.
Your class should look like this:
A.h
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getFoo() const; // const to return member and prevents modification
};
#endif // !A_H
A.cpp
#include "A.h" // you forgot to include the header
A::A() : // class constructor using it's member initializer list
foo( 5 ) {
}
int A::getFoo() const {
return foo;
}
Now once you fix your class, then working on class B should not be a problem. However there is one thing to be careful of when including a header file of one class into another; you can end up with circular includes. The best way to prevent that is to use a class prototype in the header and include its header in the containing class's cpp file. There are some cases where a class proto type will not work, but I'll leave that up to you to do the research.
How to use Class Prototype in C++
Class B might look like this:
B.h
#ifndef B_H
#define B_H
// #include "A.h" // uncomment this if prototype below doesn't work.
class A; // class prototype may not work in all cases;
// If the above prototype does not work; comment it out
// and replace it with #include "A.h".
class B {
private:
A myA;
public:
B(); // remove default
int getAValue() const;
};
#endif // !B_H
B.cpp
#include "B.h"
#include "A.h" // If class A's prototype in the header does not work
// then comment this out and place it in this class B's header by
// replacing it with the prototype.
B::B() {} // default constructor (should make this complete type)
int B::getAValue() const {
return myA.getFoo();
}
And this should help to fix your problems. If using the class prototype does not work in the header because in some cases it may not; you can remove the prototype declaration from the header and replace it with the include directive of that class and remove its include from the cpp file.
I'm new to C++ but I do have some experience in Java.
While coding, I stumbled across an error that confused me.
Here's my code (simplified, but the errors are the same):
A.h:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp:
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h:
#pragma once
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B.cpp:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
I want to pass a pointer of the a object to the bar function in B, so that I'll be able to modify and access a's fields in bar. Strangely, I get these errors when I call foo through an instance of A from another class:
1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1> main.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1> B.cpp
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C3646: 'b': unknown override specifier
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1> A.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1>d:\stuff\visual studio 2015\projects\test\test\a.cpp(5): error C2660: 'B::bar': function does not take 1 arguments
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The code works fine if I don't include A.h in B.h and I don't pass anything to the bar function.
I tried to google what could cause these errors but I wasn't able to resolve the issue by myself becuase I don't understand what's causing these errors. What am I doing wrong?
In the header file of A.h, you have:
#include "B.h"
In the header file of B.h, you have:
#include "A.h"
You have a circular include where the definition of A and B depends on each other.
A simple solution is to use forward declaration in definition of class B:
Replace the line #include "A.h" in file B.h with class B;
Add #include "A.h" at the beginning of B.cpp
Notice however, you cannot use forward declaration for class A, the reason is that you have a value b of class B as a member variable of class A:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b; /// I mean this line here more specifically
};
The compiler need to know the the definition of class B in order to determine the correct size for class A. That's why you have to put the #include "B.h" at the very beginning of A.h.
Let's take a look at B.cpp and watch what happens with the includes:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
With B.h pasted in place of the include we get:
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
And then placing A.h in place of its include:
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
And here we stop because pragma once prevents re-inclusion of B.h
We can see that in class A's definition we have B b;, but class B is not yet defined. Kaboom. A cannot be defined without B and B is not defined yet.
A must have the size of B to satisfy B b;, so it requires the full definition of B. B only needs to know A exists because it only needs a pointer to A to satisfy void bar(A *a);. So...
A.h
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h
#pragma once
class A; // forward definition of class A
class B
{
public:
B();
void bar(A *a);
};
B.cpp
#include "A.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
Both headers are referencing each other. Only one can ever actually be evaluated first by the compiler and that one cannot resolve the reference to the class in the other header. It's not obvious by the error, but the "once" #pragma is making one of the header includes not happen as you expect.
If the B.h header file does not need to know implementation details about the A class, which it does not in this case, then do not include the A.h file in B.h. Instead, change your function declaration of bar() to look like this:
bar( class A *a );
The compiler can build code from this that passes a pointer to an A object without knowing anything about what is inside of A. It doesn't need the A.h header.
Then include the A.h header file after the B.h header file in B.cpp.
I tested this and it works for me.
Do these changes:
B.h: - Forward declare A
#pragma once
// #include "A.h"
class A;
//^^^^^^
class B {
public:
B();
void bar(A *a);
};
B.cpp: #include "A.h"
//#include "B.h"
#include "A.h"
//^^^^^^^^^^^^
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
That's it.
I'm having a problem compiling with circular dependencies. I did some research, and people recommended using a forward declaration. I'm still having a problem with that because the class that has a forward declaration is using methods from the forwarded class. This causes the compiler to give me the error "Class A has incomplete field b". How can I get around the circular dependency where A requires B, and B requires A?
A.h:
#ifndef A_H_
#define A_H_
#include <iostream>
//#include "B.h"
class A
{
class B;
private:
B b;
public:
A();
~A();
void method();
};
#endif
A.cpp:
#include <iostream>
#include "A.h"
A::A()
{
}
A::~A()
{
}
void A::method()
{
b.method();
}
B.h:
#ifndef B_H_
#define B_H_
#include <iostream>
//#include "A.h"
class B
{
class A;
private:
A a;
public:
B();
~B();
void method();
};
#endif
B.cpp:
#include <iostream>
#include "B.h"
B::B()
{
}
B::~B()
{
}
void B::method()
{
a.method();
}
Your classes cannot work. Every A contains a B, which contains an A, which contains a B, etc., ad infinitum.
This will not work as you have constructed it as A requires full knowledge of the size of B and B requires the same of A, which is only given by seeing the full declaration.
The following is not valid:
class B;
class A {
B b;
};
Why? How much space do we allocate for an instance of A? sizeof(A) = sizeof(B) = undefined There is a workaround, however:
class B;
class A {
B* b_ptr;
B& b_ref;
};
This is perfectly valid, since the pointer and reference's size are known, regardless of the type they point to.
In at least one case (either A or B) you have to remove the dependence on the complete type. For example, below I've removed the need for A to have the complete type of B within the A.h header file:
// A.h
class B;
// B used as a reference only, so the complete type
// is not needed at this time
class A
{
public:
A(B& b) : b_(b) {}
void method();
private:
B& b_;
};
// A.cpp
// B is used, and the complete type is required
#include "B.h"
void A::f()
{
b.method();
}
You could try to replace one of the member by a pointer to the other class :
class B;
class A
{
private:
B* b;
public:
A();
~A();
void method();
};
I have a situation as such
A.h
#ifndef _CLASSA
#define _CLASSA
class B;
class A {
virtual void addTo(B*) {}
};
#endif
B.h
#ifndef _CLASSB
#define _CLASSB
#include "A.h"
class B : public A {
B();
void addTo(B* b) {
// blah blah blah
}
};
#endif
B.cpp
#include "B.h"
B::B() : A() {}
main.cpp
#include "B.h"
int main() {
A* b = new B();
B* d = new B();
b->addTo(d);
}
The project won't compile. If I forward declare B in the A header, the compiler complains about the expectation of a class in B.h. If I include the B.h header in A.h, the compiler can't resolve the base class. Is this possible?
Yes, include A.h in B.h and forward declare B in A.h.
If I forward declare B in the A header, the compiler complains about the expectation of a class in B.h
The way you have the code now it should work. But I suspect you're actually using B inside the method addTo, in which case a forward declaration is not enough. You need to separate the implementation to an implementation file and include B there.
EDIT: As DeadMg pointed out, class B : class A { isn't valid syntax, you probably want class B : A or class B : public A.