How to include files for virtual methods? - c++

I have two class hierarchies: As and Bs. As have a virtual method return Bs, and Bs have a virtual method return As.
A.h
#pragma once
class B;
struct A
{
virtual B* f() = 0;
};
A1.h
#pragma once
#include "A.h"
#include "B1.h"
struct A1 : public A
{
B1* f() override;
};
B.h
#pragma once
class A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
#include "A1.h"
struct B1 : public B
{
A1* g() override;
};
It doesn't compile with errors in VS2015
overriding virtual function return type differs and is not covariant from A
With class forward declaration
class A1 : public A;
it should work. But C++ doesn't support such class forward declaration. How to fix it?

When dealing with circular references, use forward declarations instead of #include statements where appropriate.
Also, the header files themselves should have guards in them to avoid declaring their content multiple times when #include'd multiple times. The guards themselves can use either an #ifndef/#define pair, or a #pragma once, depending on your compiler.
A.h
#ifndef A_H
#define A_H
struct B;
struct A
{
virtual B* f() = 0;
};
#endif
Or:
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#ifndef A1_H
#define A1_H
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
#endif
Or:
#pragma once
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
A2.h
#ifndef A2_H
#define A2_H
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
#endif
Or:
#pragma once
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
B.h
#ifndef B_H
#define B_H
struct A;
struct B
{
virtual A* g() = 0;
};
#endif
Or:
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
#endif
Or:
#pragma once
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
B2.h
#ifndef B2_H
#define B2_H
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
#endif
Or
#pragma once
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
The #include statements to satisfy the forward-declared classes should be used in the method implementation source files, not in their declaring header files:
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B1* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B2* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A1* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A2* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
That being said, forward declaring the structs is the only way to deal with circular references. But since you can't forward declare hierarchies, I don't think there is a solution to your problem without rethinking your design. If that is not an option, you will have to stay way from using covariant return values.
A.h
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#pragma once
#include "A.h"
struct A1 : public A
{
B* f() override;
};
A2.h
#pragma once
#include "A.h"
struct A2 : public A
{
B* f() override;
};
B.h
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
struct B1 : public B
{
A* g() override;
};
B2.h
#pragma once
#include "B.h"
struct B2
{
A* g() override;
};
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
It just means you will have to use type-casts wherever you were relying on covariance when calling f() and g().

Related

C++ inheritance & virtual function problem

I want to show result is 2. (Now result is 1.)
How should I do? (I want to call B::test(). But Actually code cannot access b.h, b.c in main.c)
also I want to know that error from "public: virtual int test() {return 1;}" to "protected: virtual int test() {return 1;}" in a.h
the inheritance relationship are
super class A sub class B
super class A sub class C
but I can access A class in main.c
I want to result 2. ("a.test()" could not call "b.test()")
// a.h
#ifndef _A_
#define _A_
class A {
public:
A() {};
~A() {};
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
#endif
// b.h
#ifndef _B_
#define _B_
#include "a.h"
class B : public A {
public:
B() {};
~B() {};
private:
int test() override;
friend class A;
};
#endif
// b.c
#include "b.h"
int B::test()
{
return 2;
}
// c.h
#ifndef _C_
#define _C_
#include "a.h"
class C : public A {
public:
C() {};
~C() {};
private:
int test() override;
friend class A;
};
#endif
// c.c
#include "c.h"
int C::test()
{
return 3;
}
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
Consider your code:
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
The key decider on behaviour is =new A().
If you change this to =new B() then you would get the result of '2' that you want.
However, you've had added the restriction 'code cannot access b.h'. This means that =new B() will not compile. Where does this restriction come from? You could achieve this with an extremely complicated factory pattern, but it seems unlikely this is what you are trying to do.
Access specifiers (private, protect, public) should be the same for the same method (test() in this case) at every level in the hierarchy. This is not absolutely enforced by the compiler, but is a clear best practice. There's very little difference her between making test() private or protected, but in both cases the expression:
a->test()
will fail in main, because it is outside of the class, and can only access public members.
Also worth pointing out that your friend declarations are entirely unnecessary in the code as shown.
Create object of type B, you still will be able to call test method, because A::test is public. This code will print 2:
int main(void)
{
A *a = new B();
// ^
cout << a->test() << "\n";
delete a; // (1)
return 0;
}
Also line (1) won't work properly unless you make A's destructor virtual (When to use virtual destructors?):
class A {
public:
A() {};
virtual ~A() {};
// ^^^^^^^
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
UPD If for some reason you can't include b.h you can do the following:
a.h:
#ifndef _A_
#define _A_
class A {
...
};
A* CreateB();
#endif
a.c:
#include "a.h"
#include "b.h"
...
A* CreateB() {
return new B();
}
main.c:
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = CreateB();
cout << a->test() << "\n";
delete a;
return 0;
}

Why does cout give me the wrong integer?

When I build and run this code in Eclipse CDT, I expect it to print 1. It prints -1992206527 instead. Why is this?
Here's my code.
A.h
#ifndef A_H
#define A_H
class A {
private:
int a;
public:
A();
~A();
void printNum();
};
#endif
A.cpp
#include <iostream>
#include "A.h"
A::A() :
a(1)
{
}
A::~A(){}
void A::printNum(){
std::cout << a << std::endl;
}
B.h
#ifndef B_H_
#define B_H_
class A;
class B {
private:
A* obj;
public:
B();
~B();
int run();
};
#endif
B.cpp
#include "A.h"
#include "B.h"
B::B() {}
B::~B() {}
int B::run(){
obj->printNum();
return 0;
}
main.cpp
#include "B.h"
int main(int argc, char **argv) {
B b;
return b.run();
}
To make it print 1, you must initialize B::obj. Below is a B.cpp with obj being properly initialized/ deallocated.
#include "A.h"
#include "B.h"
B::B() : obj(new A) {}
B::~B() { delete obj;}
int B::run(){
obj->printNum();
return 0;
}
Alternatively, you could make obj be an object type A(i.e declare obj as A obj;), instead of making it a pointer to an object of type A. This would necessitate including A.hin B.h.

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

Slaying the Circular Dependence

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

Access member of class from a constructor of another class

My code looks something like this:
main.cpp
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main(){
int d,f;
A c();
d = c.GetStuff();
B *d = new C();
f = d->Get();
return 0;
}
A.h
#ifndef A_H
#define A_H
class A
{
int a;
public A();
int GetStuff() {return(a) ;}
};
#endif
A.cpp
#include "A.h"
A::A()
{
a = 42;//just some value for sake of illustration
}
B.h
#ifndef B_H
#define B_H
Class B
{
public:
virtual int Get(void) =0;
};
class C: public B {
public:
C();
int Get(void) {return(a);}
};
#endif
B.cpp
#include "B.h"
C::C() {
a // want to access this int a that occurs in A.cpp
}
My question is, what is the best way to gain access to "a" in B.cpp?
I tried using class "friend", but I am not getting results.
Any suggestions?
Thanks!
Two different answers, depending on what you mean
If each A object is meant to have it's own unique 'a' variable (which is how you've defined it) then you'll need to pass an A into the constructor of C:
C::C(const A &anA) {
int foo= anA.a; //
}
And, invoking the constructor becomes:
A myA;
B *myC = new C(myA); // You picked confusing names for your classes and objects
However, if you intended all A objects to share a common a value, then you should declare a and getStuff as static in A :
class A
{
static int a;
public:
static int GetStuff() {return a;};
... and access it as A::GetStuff() in the C constructor.