So i have 2 classes let's call it class A and B which inside of those classes have a reference for each other as a function's arguments. When i try to forward declare it like this:
// A.h (Header guarded)
namespace ns {
class B { // Attempt to forward declare B
public:
int getRand();
};
class A {
public:
float a, b;
void aFunc(B &b);
};
}
// B.h (Header guarded)
namespace ns {
class A { // Attempt to forward declare A
public:
float a, b;
};
class B {
public:
void bFunc(A &a);
int getRand();
};
}
The thing is, when i do this i got 'class' type redefinition error. I've been searching for the solution and still haven't came to a solution. Am i doing this right? Which i suppose i'm not, can you tell me where did i do wrong here?
They're not forward declaration, they're definition definitely.
You should
// A.h (Header guarded)
namespace ns {
class B; // forward declare B
class A {
public:
// Some functions with B references as arguments
};
}
And it's same for B.h.
According to your situation, there're just some member functions which take forward declared class as parameters, you can leave the declaration of member functions in .h file, and provide their definition in .cpp file. Such as
// A.h (Header guarded)
namespace ns {
class B; // forward declare B
class A {
public:
float a, b;
void aFunc(B &b);
};
}
// B.h (Header guarded)
namespace ns {
class A; // forward declare A
class B {
public:
void bFunc(A &a);
int getRand();
};
}
// A.cpp
#include "A.h"
#include "B.h"
namespace ns {
void A::aFunc(B& b) { /* ... */ }
}
// B.cpp
#include "A.h"
#include "B.h"
namespace ns {
void B::bFunc(A& b) { /* ... */ }
int B::getRand() { /* ... */ }
}
Related
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;
};
Header.h
#pragma once
namespace
{
class B;
}
namespace n1
{
namespace n2
{
class A
{
private:
int i;
public:
friend class B;
};
}
}
Source.cpp
#include <stdio.h>
#include "Header.h"
class B
{
public:
void Run();
};
void B::Run()
{
n1::n2::A a;
a.i;
}
int main()
{
B b;
b.Run();
}
As we can see from above Class A is defined in header file while class B is defined in source file. I want to access private member of Class A from Class B::run(). I am not able to find the way to do this.
you are forward declaring class B in anonymous namespace
take out class B forward declaration out of the namespace and it should work
like this:
#pragma once
class B;
namespace n1
{
namespace n2
{
class A
{
private:
int i;
public:
friend class B;
};
}
}
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>(); }
};
I recently got stuck in a situation like this:
class A
{
public:
typedef struct/class {…} B;
…
C::D *someField;
}
class C
{
public:
typedef struct/class {…} D;
…
A::B *someField;
}
Usually you can declare a class name:
class A;
But you can't forward declare a nested type, the following causes compilation error.
class C::D;
Any ideas?
You can't do it, it's a hole in the C++ language. You'll have to un-nest at least one of the nested classes.
class IDontControl
{
class Nested
{
Nested(int i);
};
};
I needed a forward reference like:
class IDontControl::Nested; // But this doesn't work.
My workaround was:
class IDontControl_Nested; // Forward reference to distinct name.
Later when I could use the full definition:
#include <idontcontrol.h>
// I defined the forward ref like this:
class IDontControl_Nested : public IDontControl::Nested
{
// Needed to make a forwarding constructor here
IDontControl_Nested(int i) : Nested(i) { }
};
This technique would probably be more trouble than it's worth if there were complicated constructors or other special member functions that weren't inherited smoothly. I could imagine certain template magic reacting badly.
But in my very simple case, it seems to work.
If you really want to avoid #including the nasty header file in your header file, you could do this:
hpp file:
class MyClass
{
public:
template<typename ThrowAway>
void doesStuff();
};
cpp file
#include "MyClass.hpp"
#include "Annoying-3rd-party.hpp"
template<> void MyClass::doesStuff<This::Is::An::Embedded::Type>()
{
// ...
}
But then:
you will have to specify the embedded type at call time (especially if your function does not take any parameters of the embedded type)
your function can not be virtual (because it is a template)
So, yeah, tradeoffs...
I would not call this an answer, but nonetheless an interesting find:
If you repeat the declaration of your struct in a namespace called C, everything is fine (in gcc at least).
When the class definition of C is found, it seems to silently overwrite the namspace C.
namespace C {
typedef struct {} D;
}
class A
{
public:
typedef struct/class {...} B;
...
C::D *someField;
}
class C
{
public:
typedef struct/class {...} D;
...
A::B *someField;
}
If you have access to change the source code of classes C and D, then you can take out class D separately, and enter a synonym for it in class C:
class CD {
};
class C {
public:
using D = CD;
};
class CD;
This would be a workaround (at least for the problem described in the question -- not for the actual problem, i.e., when not having control over the definition of C):
class C_base {
public:
class D { }; // definition of C::D
// can also just be forward declared, if it needs members of A or A::B
};
class A {
public:
class B { };
C_base::D *someField; // need to call it C_base::D here
};
class C : public C_base { // inherits C_base::D
public:
// Danger: Do not redeclare class D here!!
// Depending on your compiler flags, you may not even get a warning
// class D { };
A::B *someField;
};
int main() {
A a;
C::D * test = a.someField; // here it can be called C::D
}
This can be done by forward declare the outer class as a namespace.
Sample: We have to use a nested class others::A::Nested in others_a.h, which is out of our control.
others_a.h
namespace others {
struct A {
struct Nested {
Nested(int i) :i(i) {}
int i{};
void print() const { std::cout << i << std::endl; }
};
};
}
my_class.h
#ifndef MY_CLASS_CPP
// A is actually a class
namespace others { namespace A { class Nested; } }
#endif
class MyClass {
public:
MyClass(int i);
~MyClass();
void print() const;
private:
std::unique_ptr<others::A::Nested> _aNested;
};
my_class.cpp
#include "others_a.h"
#define MY_CLASS_CPP // Must before include my_class.h
#include "my_class.h"
MyClass::MyClass(int i) :
_aNested(std::make_unique<others::A::Nested>(i)) {}
MyClass::~MyClass() {}
void MyClass::print() const {
_aNested->print();
}
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.