C++ Forward Declaration and Inheritence - c++

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.

Related

Is it possible to have restricted access to included class?

I have a class say A in A.h file and class B: public A in B.h file.
A.h file
#ifndef A_H
#define A_H
class A
{
public:
void foo {}
};
#endif
B.h file
#ifndef B_H
#define B_H
#include "A.h"
class B: public A
{
...
};
#endif
Is there a way to include B but not to have access to A until I include A.h?
Like this
#include "B.h"
main() {
B* b = new B(); //OK
b->foo(); //OK
A* a = new A(); //Error
a->foo(); //Error
}
No. B.h depends on the definition of A, so there is no way to include B.h without including the definition of A. And there is no way of getting around that dependency if B must be defined in B.h and if B must inherit A.
You can make the creation of separate A into an error by changing A to be an abstract type. But that would remain an error even if A.h was included separately.

Co-Dependent .h files with forward declaration

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

Circular inclusion issue with extended class c++

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;
};

c++ header inclusion order with conditional compilation

Say I have two files A.hpp and B.hpp
A.hpp:
#indef DEF_A
#define DEF_A
class A{
/*implementation of class A*/
/*some part of it needs B*/
#ifdef DEF_B
void method(B b){/*do something with B*/}
#endif
}
#endif
B.hpp:
#indef DEF_B
#define DEF_B
class B{
/*implementation of class B*/
/*some part of it needs A*/
#ifdef DEF_A
void method(A a){/*do something with A*/}
#endif
}
#endif
I don't want to inclue A.hpp in B.hpp (or vice-versa) because then every time I need A.hpp I will need B.hpp (or vice-versa).
But when in the main file I write :
main.cpp
#include"A.hpp"
#include"B.hpp"
int main(){
A a;
B b;
}
A::method(B b) is unknown. If I reverse the inclusion order I will only have B::method(A a).
Is there a way to have access to both methods when the two headers are included ?
[edit]
The method should also work for template class with no .cpp file.
[/edit]
I would use forward declaration, something like:
A.hpp
#indef DEF_A
#define DEF_A
class B; // Forward declaration of B
class A { // Definition of A
public:
void method(const B& b);
};
#endif
A.cpp
#include "A.hpp"
#include "B.hpp"
void A::method(const B& b) { /* your implementation */ }
B.hpp
#indef DEF_B
#define DEF_B
class A; // Forward declaration of A
class B { // Definition of B
public:
void method(const A& a);
};
#endif
B.cpp
#include "B.hpp"
#include "A.hpp"
void B::method(const A& a) { /* your implementation */ }
And then in main.cpp
you include both A.hpp and B.hpp as you use both of them.
But if in C.cpp you use only A (without B) you can do
C.cpp
#include "A.hpp"
void foo()
{
A a;
// B b; // If uncommented, that would fail to compile.
}
maybe you should give the pimpl-idiom a try. You could easily hide the implementation details in .cpp file, even if its about a templated classes:
//Important: fwd declaration as Jarod42 already stated!
class B;
class AImpl;
class A
{
void aMethod( B* b )
{
impl->( b );
}
AImpl* impl; //this will work because compiler need not to know
//exact object size as we are creating a pointer or
//reference...type definition in cpp
}
// same here for B;
//in cpp file of A and B:
class AImpl : public TemplateClass<X>
{
void aMethod( B* b ){}
};
I hope this will help you with your problem!

In C++, I want two classes to access each other

I have two classes, class A and class B.
A.h -> A.cpp
B.h -> B.cpp
And then, I set B as a member in class A. Then, class A can access class B by
#include <B.h>
But, how can I get the pointer of class A in class B and access the public member of class A?
I found some information about on the internet: a Cross-class. They said you can make it by setting the class B as a nested class in class A.
Do you have any other advice?
sorry.
myCode: as follow..
class A:
#ifndef A
#define A
#include "B.h"
class A
{
public:
A() {
b = new B(this);
}
private:
B* b;
};
#endif
#ifndef B
#define B
#include"A.h"
class B
{
public:
B(A* parent = 0) {
this->parent = parent;
}
private:
A* parent;
};
#endif
Just use forward declaration. Like:
A.h:
#ifndef A_h
#define A_h
class B; // B forward-declaration
class A // A definition
{
public:
B * pb; // legal, we don't need B's definition to declare a pointer to B
B b; // illegal! B is an incomplete type here
void method();
};
#endif
B.h:
#ifndef B_h
#define B_h
#include "A.h" // including definition of A
class B // definition of B
{
public:
A * pa; // legal, pointer is always a pointer
A a; // legal too, since we've included A's *definition* already
void method();
};
#endif
A.cpp
#inlude "A.h"
#incude "B.h"
A::method()
{
pb->method(); // we've included the definition of B already,
// and now we can access its members via the pointer.
}
B.cpp
#inlude "A.h"
#incude "B.h"
B::method()
{
pa->method(); // we've included the definition of A already
a.method(); // ...or like this, if we want B to own an instance of A,
// rather than just refer to it by a pointer.
}
Knowing that B is a class is enough for compiler to define pointer to B, whatever B is. Of course, both .cpp files should include A.h and B.h to be able to access class members.