C++ cyclic dependency of classes (Singleton) - c++

i have a problem to compile the classes with cyclic dependency, and i can not find the way to compile my code
the main problem is appeared in chain of classes that has dependency to each others
for example i have 6 header files(Classes) (A, B, C, D, E, F)
A included in E
F, D included in A
E included in F, D
now i have a loop and cant fix it
i simplify the problem then create the simple example to show what is my exact problem
A.h
#ifndef A_H
#define A_H
#include "B.h"
class A
{
public:
static A& getInstance()
{
static A instance;
return instance;
}
int i;
int sum()
{
return i+B::getInstance().j;
}
private:
A() {}
};
#endif
B.h
#ifndef B_H
#define B_H
#include "A.h"
class B
{
public:
static B& getInstance()
{
static B instance;
return instance;
}
int j;
int sum()
{
return j+A::getInstance().j;
}
private:
B() {}
};
#endif
main.cpp
#include "A.h"
#include "B.h"
#include <iostream>
int main()
{
A::getInstance().i=1;
B::getInstance().j=2;
int t1=A::getInstance().sum();
int t2=B::getInstance().sum();
std::cout<<t1<<std::endl;
std::cout<<t2<<std::endl;
return 0;
}
g++ main.cpp
In file included from A.h:3:0,
from main.cpp:1:
B.h: In member function ‘int B::sum()’:
B.h:17:12: error: ‘A’ has not been declared
return j+A::getInstance().j;
is there any way or solutions to resolve this?

If you can't use .cpp files for some reason, you can do this:
a.h:
#pragma once
class A {
public:
static A& getInstance();
int i;
int sum();
private:
A();
};
a_impl.h:
#pragma once
#include "a.h"
#include "b.h"
inline A& A::getInstance() {
static A instance;
return instance;
}
inline int A::sum() {
return i + B::getInstance().j;
}
inline A::A() {
}
b.h:
#pragma once
class B {
public:
static B& getInstance();
int j;
int sum();
private:
B();
};
b_impl.h:
#pragma once
#include "a.h"
#include "b.h"
inline B& B::getInstance() {
static B instance;
return instance;
}
inline int B::sum() {
return j + A::getInstance().i;
}
inline B::B() {
}
And then first include declarations a.h and b.h, and then implementations a_impl.h and b_impl.h:
#include "a.h"
#include "b.h"
#include "a_impl.h"
#include "b_impl.h"
#include <iostream>
int main() {
A::getInstance().i = 1;
B::getInstance().j = 2;
int t1 = A::getInstance().sum();
int t2 = B::getInstance().sum();
std::cout << t1 << std::endl;
std::cout << t2 << std::endl;
}
Now it will compile. In this particular example, B (or A) could've been implemented inside class definition (so, no b_impl.h). I separated declarations and definitions for both classes for the sake of symmetry.

Related

I need to include two header files to each other not using forward declaration cause get "incomplete type" error

I need to include two header files to each other but I have trouble doing this. Is there any way except using forward declaration and template to do this ? or I'm not allowed to do it in c++?
here is what I want to do:
// A.hpp file
#ifndef H_A_H
#define H_A_H
#include "B.hpp"
class A {
private:
vector<B*> b;
public:
void function() {
// using methods of B
}
};
#endif
// B.hpp file
#ifndef H_B_H
#define H_B_H
#include "A.hpp"
class B {
private:
vector<A*> a;
public:
void function() {
// using methods of A
}
};
#endif
You can't include two header files to each other. There should be forward declaration in one of the files and function definition has to be pushed to .cpp file where you can include the header file.
// HeaderA.h file
#ifndef H_A_H
#define H_A_H
#include "HeaderB.h"
class A {
private:
int b;
public:
void function() {
// using methods of B
B b;
b.function();
}
};
#endif
// HeaderB.h file
#ifndef H_B_H
#define H_B_H
class A;
class B {
private:
int a;
public:
void function();
};
#endif
// Main.cpp
#include "HeaderA.h"
#include "HeaderB.h"
void B::function()
{
// using methods of A
A a;
a.function();
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
You have a cyclic dependency. This answer explains how to deal with them via forward declarations.
This article also deals with cyclic dependencies.
If you 100% don't want to use forward declarations and it is possible you can split logic in a different class and use composition.
// SomeLogic.h
class SomeLogic
{
};
// A.h
#include "SomeLogic.h"
class A
{
SomeLogic someLogic;
};
// B.h
#include "SomeLogic.h"
class B
{
SomeLogic someLogic;
};

Circular dependency with template function

I have a class A with the following declaration (A.h file):
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#endif
and a class B deriving from that class (B.h file):
#ifndef __B_DEFINED__
#define __B_DEFINED__
#include <iostream>
#include "A.h"
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
So far, so good. My issue is that the function A::doThat() uses B::doThis():
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
Usually, the circular dependency would not be an issue because I would just define A::doThat() in the .cpp file. In my case however, doThat is a template function so I can't do that.
Here are the solutions I have envisioned so far:
Defining the template function A::doThat() in a .cpp file. The issue with that is that I need to instantiate explicitly all the calls with various template arguments (there might be many in the real case).
After the declaration of the A class in A.h, add #include "B.h" and then define the A::doThat() function. This works fine in visual studio but g++ does not like it.
Is there a neat way to solve this problem?
EDIT: In the real case, there is not just one child class B, but several (B, C, D, etc.) The function A::doThat() depends on all of them. The function B::doThis() is also templated.
A default template parameter for the B class could work:
#include <iostream>
// include A.h
class B;
class A
{
public:
template<typename T, typename U = B> inline void doThat() const
{
U b; b.doThis();
}
};
// include B.h
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
// main
int main()
{
A a;
a.doThat<int>();
}
Usually the best way to allow a parent to call a child function is to declare the function as a pure virtual function in the parent and override it in the children.
#include <iostream>
class A
{
public:
virtual ~A() = default;
template<typename T> inline void doThat() const
{
// do some other stuff
doThis();
}
virtual void doThis() const = 0; // pure virtual function
};
class B: public A
{
public:
void doThis() const override
{
std::cout << "do this!" << std::endl;
}
};
int main()
{
B b;
A* ap = &b;
ap->doThat<int>();
}
The following does work with g++:
File A.h:
#ifndef __A_DEFINED__
#define __A_DEFINED__
class A
{
public:
template<typename T> inline void doThat() const;
};
#include "B.h"
template<typename T> inline void A::doThat() const { B b; b.doThis(); }
#endif
File B.h:
#include <iostream>
#include "A.h"
// We check for the include guard and set it AFTER the inclusion of A.h
// to make sure that B.h is completely included from A.h again.
// Otherwise the definition of A::doThat() would cause a compiler error
// when a program includes B.h without having included A.h before.
#ifndef __B_DEFINED__
#define __B_DEFINED__
class B : public A
{
public:
void doThis() const { std::cout << "do this!" << std::endl; }
};
#endif
File test_A.cpp:
// In this test case we directly include and use only A.
#include "A.h"
#include "A.h" // We test whether multiple inclusion causes trouble.
int main() {
A a;
a.doThat<int>();
}
File test_B.cpp:
// In this test case we directly include and use only B.
#include "B.h"
#include "B.h" // We test whether multiple inclusion causes trouble.
int main() {
B b;
b.doThat<int>();
b.doThis();
}
Alternative Idea:
I do not know whether you (or some coding conventions) insist on separate header files for each class, but if not the following should work:
You can put the definitions of class A and class B and of the member function template A::doThat<typename>() (in this order) together in one header file AandB.h (or whatever name you like).
This cries for polymorphism. There are two options using polymorphism:
Dynamic polymorphism, i.e. make A an abstract base class and call doThis() virtually:
struct A
{
virtual void do_this() const = 0;
template<typename T>
void doThat() const { doThis(); }
};
struct B : A
{
void doThis() const override { /* ... */ }
};
Of course, this only works if doThis() is not templated. If you need that, you could use
Static polymorphism, i.e. CRTP, when
template<typename Derived>
struct A
{
template<typename T>
void doThat() const { static_cast<const Derived*>(this)->template doThis<T>(); }
};
struct B : A<B>
{
template<typename T>
void doThis() const { /* ... */ }
};
If (as in your example code) B::doThis() is not called for the same object, but for some temporary, you could
template<typename typeB>
struct A
{
template<typename T>
void doThat() const { typeB b; b.template doThis<T>(); }
};

Circular includes due to enum within a class in C++

I have an interesting variant of the oft-repeated C++ circular include dilemma. In short: I want to use an enum that is defined in a subclass as the type of an instance variable in a parent class. Here's a minimal example:
a.h
#ifndef A_H
#define A_H
#include "c.h"
class ClassA
{
public:
ClassA() {};
void setStatus(ClassC::Status status) { a_status = status; }
void setA(int val) { a_var = val; }
int valueA() { return a_var; }
ClassC::Status status() { return a_status; }
private:
int a_var;
ClassC::Status a_status;
};
#endif // A_H
c.h
#ifndef C_H
#define C_H
#include "a.h"
class ClassC : public ClassA
{
public:
enum Status
{
Valid,
Invalid
};
ClassC(): ClassA() {};
void setC(int val) { c_var = val; }
int valueC() { return c_var; }
private:
int c_var;
};
#endif // C_H
main.cpp
#include "a.h"
int main(int argc, const char *argv[])
{
ClassA *obj = new ClassA();
return 0;
}
I can't forward declare the enum in a.h because the name of the enum has to be simple, and ClassC::Status isn't. It's important that the enum be within the namespace of the child class, because there are lots of such classes, and I need to isolate the names of the enum items from values in other enumcs. Any ideas?
In short: I want to use an enum that is defined in a subclass as the type of an instance variable in a parent class.
You cannot do that. You'll need to come up with a different mechanism.

Circular dependencies C++

I'm trying to compile something like the following:
A.h
#include "B.h"
class A {
B * b;
void oneMethod();
void otherMethod();
};
A.cpp
#include "A.h"
void A::oneMethod() { b->otherMethod() }
void A::otherMethod() {}
B.h
#include "A.h"
class B {
A * a;
void oneMethod();
void otherMethod();
};
B.cpp
#include "B.h"
void B::oneMethod() { a->otherMethod() }
void B::otherMethod() {}
Until now I haven't had problems using forward declarations, but I can use that now, because i can't use atributtes or methods of only-forward-declarated classes.
How can I solve this?
In C++, unlike Java and C#, you can define a member function (providing its body) outside the class.
class A;
class B;
class A {
B * b;
void oneMethod();
void otherMethod() {}
};
class B {
A * a;
void oneMethod();
void otherMethod() {}
};
inline void A::oneMethod() { b->otherMethod(); }
inline void B::oneMethod() { a->otherMethod(); }
As long as I'm understanding your question right, all you need to do is this:
A.h
class B;// Forward declaration, the header only needs to know that B exists
class A {
B * b;
void oneMethod();
void otherMethod();
};
A.cpp
#include "A.h"
#include "B.h"//Include in the .cpp since it is only compiled once, thus avoiding circular dependency
void A::oneMethod() { b->otherMethod() }
void A::otherMethod() {}
B.h
class A;// Forward declaration, the header only needs to know that A exists
class B {
A * a;
void oneMethod();
void otherMethod();
};
B.cpp
#include "B.h"
#include "A.h"//Include in the .cpp since it is only compiled once, thus avoiding circular dependency
void B::oneMethod() { a->otherMethod() }
void B::otherMethod() {}
You must defer using the members of a class until after that class is defined. In your case, that means moving some member function bodies to the bottom of the file:
class B;
class A {
B * b;
void oneMethod();
void otherMethod() {}
};
class B {
A * a;
void oneMethod() { a->otherMethod() }
void otherMethod() {}
};
inline void A::oneMethod() { b->otherMethod() }
Here is a typical solution in multiple files:
A.h
class B;
class A {
B * b;
void oneMethod();
void otherMethod();
};
B.h
class A;
class B {
A * a;
void oneMethod();
void otherMethod();
};
A.cpp
#include "A.h"
#include "B.h"
void A::oneMethod() { b->otherMethod() }
void A::otherMethod() {}
B.cpp
#include "A.h"
#include "B.h"
void B::oneMethod() { a->otherMethod() }
void B::otherMethod() {}
main.cpp
#include "A.h"
int main () { A a; a.oneMethod(); }
Push the implementation of your functions into cpp files and then the cpp can include both headers.

Common Practice for Template Function Defination - Mix with Function Declaration?

Most of the time, I "avoid" to have the following style in my single header file.
class a {
void fun();
};
void a::fun() {
}
In order to avoid the following error. I try to separate class definition in cpp file and class declaration in h file. For example, the below is the wrong example :
main.cpp
#include "b.h"
#include "a.h"
int main()
{
a aa;
b bb;
}
a.h
#ifndef A_H
#define A_H
#include <iostream>
class a {
public:
virtual int fun();
};
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
b.h
#ifndef B_H
#define B_H
#include <iostream>
#include "a.h"
class b {
public:
b();
};
#endif
b.cpp
#include "b.h"
#include "a.h"
b::b()
{
a aa;
aa.fun();
}
I will get the following error :
1>b.obj : error LNK2005: "public: virtual int __thiscall a::fun(void)" (?fun#a##UAEHXZ) already defined in main.obj
However, when come to template, I will usually do it this way :
a.h
#ifndef A_H
#define A_H
#include <iostream>
template <typename T>
class a {
public:
virtual T fun();
};
template<typename T> T a<T>::fun()
{
T t;
std::cout << "a" << std::endl;
return t;
}
#endif
May I know it this a good practice?
Thanks.
Cheok
You can eliminate the LNK2005 error by declaring the definition of a::fun() as inline. For example:
// a.h
// ...
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
With templates, the problem doesn't occur because the compiler/linker take care of ensuring that there is only one definition of each template instantiation.
If, for some reason, you don't want the function to be inline, then you'll have to ensure that it only gets compiled once. For example, something like this:
// a.h
// ...
#ifdef DEFINE_CLASS_A_FUNCTIONS
int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
#endif
and then, somewhere, you'll need to do something like this (exactly once):
#define DEFINE_CLASS_A_FUNCTIONS
#include "a.h"
1>b.obj : error LNK2005: "public:
virtual int __thiscall a::fun(void)"
(?fun#a##UAEHXZ) already defined in
main.obj
You are getting this error because a::fun() is not inline
inline int a::fun()
{
int t;
std::cout << "a" << std::endl;
return t;
}
Also, refer C++ FAQ : How can I avoid linker errors with my template functions?