C++ Can a class pass itself by reference? - c++

Trying to pass a parent class object to a child class object so that the child class object has control over the parent class object's methods.
This is however resulting in header related issues.
I've tried forward declaring one of the classes but it seems whatever class is declared first always has trouble reading from the class declared below.
Both errors refer to Device' constructor where try to call dm's hello world method, they are:
Use of undefined type 'DeviceManager'
Left of '->HelloWorld' must point to class/struct/union/generic type
...
//main.cpp
#include "parent.h"
void main()
{
cout << "Created DeviceManager\n";
DeviceManager* deviceManager = 0;
deviceManager = new DeviceManager;
cout << "Giving DeviceManager a device\n";
deviceManager->p = new Device(deviceManager);
cout << "Giving Device a reference to DevicenManager\n";
deviceManager->Share();
}
...
class DeviceManager;
class Device
{
public:
Device(DeviceManager* manager)
{
dm = 0;
this->dm = manager;
this->dm->HelloWorld();
}
DeviceManager* dm;
};
//device manager
class DeviceManager
{
public:
DeviceManager()
{
p = 0;
}
void HelloWorld()
{
//if this calls we know the child has control over the parent.
cout << "Hello World";
}
Device* p;
};

Yes.
To solve circular dependencies with class member and function declarations, you can forward-declare a class:
class A;
class B {
A *a;
};
class A {
B *b;
};
To define class member functions that access members of the other class, you must define the function after the other class has been defined:
class B;
class A {
public:
void f(B &arg);
};
class B {
public:
void g(A &arg);
};
void A::f(B &arg) {
arg.g(*this);
}
void B::g(A &arg) {
arg.f(*this);
}
Usually, in a C++ project, you wouldn't even encounter this problem: You would put function definitions, i.e. implementations, into .cpp files, while putting the class definitions into header files. Class forward declarations, if neccesary, could be put into their own header files that are included by all headers that need them.
A full example of how you would split the above code into multiple files:
a.cpp
#include "a.h"
#include "b.h"
void A::f(B &arg) {
arg.g(*this);
}
b.cpp
#include "b.h"
#include "a.h"
void B::g(A &arg) {
arg.f(*this);
}
a.h
#ifndef _A_H_
#define _A_H_
#include "forward_declarations.h"
class A {
public:
void f(B &arg);
};
#endif //_A_H_
b.h
#ifndef _B_H_
#define _B_H_
#include "forward_declarations.h"
class B {
public:
void g(A &arg);
};
#endif //_B_H_
forward_declarations.h
#ifndef _FORWARD_DECLARATIONS_H_
#define _FORWARD_DECLARATIONS_H_
class A;
class B;
#endif //_FORWARD_DECLARATIONS_H_
As a general rule of thumb, if you need to forward-declare a class, you might have misdesigned something and should think about whether there is a better way (but there also are perfectly valid use cases that require class forward declarations).
If you don't understand my #ifndef, #define and #endif preprocessor lines: These are header guards, and should be used with all files that are included somewhere else, exception you know precisely what you're doing. Believe me. You'll regret ommiting one.

If your problem is cyclic dependancy, like this:
// DeviceManager.h
#include "device.h"
class DeviceManager
{
DeviceManager(Device& device) {}
};
// Device.h
#include "DeviceManager.h"
class Device
{
Device(DeviceManager& manager) {}
};
You can solve the problem be forward declaring one of the classes, and passing the object by pointer.
// Device.h
//#include "DeviceManager.h"
class DeviceManager;
class Device
{
Device(DeviceManager* manager) {}
};

Related

Class method friend of another class in two separate files

My goal is simple - I want to access the protected members of one class from the methods of another class. For this I have the following -
A.HPP
#ifndef A_HPP
#define A_HPP
#include "B.hpp"
using namespace std;
class A
{
protected:
int a;
public:
A();
~A(){};
friend void B::geta(A& ao);
};
inline A::A()
{
a = 2;
cout << a;
}
#endif
B.HPP
#ifndef B_HPP
#define B_HPP
using namespace std;
class A;
class B
{
protected:
int b;
public:
B();
~B(){};
void geta(A& ao);
};
inline B::B()
{
b = 1;
cout << b;
}
inline void B::geta(A& ao)
{
b = ao.a;
cout << b;
}
#endif
MAIN.CPP
#include <iostream>
#include "A.hpp"
#include "B.hpp"
int main()
{
A ao;
B bo;
bo.geta(ao);
return 0;
}
When I compile this I get the following error.
How do I fix this? Most answers that I see here are just putting all classes in one file and defining functions in appropriate positions to achieve this but I need them in separate files.
Option 1: Not inline
You can of course move the definition of B::geta to a B.cpp file which includes A.hpp and remove the inline keyword. But this might make compiler optimizations less likely.
Option 2: Weird #include logic
Your definitions as they are can only compile if the compiler sees a forward declaration of A, the definition of B, the definition of A, and the definition of B::geta, all in that order. So if you want the definition of A in one file and the definition of B in another, you'll need to get the preprocessor to do some switching back and forth between files.
A.hpp
// NO A_HPP include guard!
#ifdef INCLUDED_FROM_B_HPP
class A
{
protected:
int a;
public:
A();
~A(){};
friend void B::geta(A& ao);
};
inline A::A()
{
a = 2;
cout << a;
}
#else
# include "B.hpp"
#endif
B.hpp
#ifndef B_HPP
#define B_HPP
class A;
class B
{
protected:
int b;
public:
B();
~B(){};
void geta(A& ao);
};
#define INCLUDED_FROM_B_HPP
#include "A.hpp"
#undef INCLUDED_FROM_B_HPP
inline B::B()
{
b = 1;
cout << b;
}
inline void B::geta(A& ao)
{
b = ao.a;
cout << b;
}
#endif
So now if a file does #include "B.hpp", the preprocessor will:
Output the class A; and definition of B from the first part of B.hpp.
Define INCLUDED_FROM_B_HPP.
Output the definitions in A.hpp.
Clear the definition of INCLUDED_FROM_B_HPP.
Output the definitions of inline members of B from the second part of B.hpp.
If a file does #include "A.hpp" first, things are a bit trickier:
Since INCLUDED_FROM_B_HPP is not set, just immediately go into B.hpp.
Output the class A; and definition of B from the first part of B.hpp.
Define INCLUDED_FROM_B_HPP.
When the #include "A.hpp" in the middle of B.hpp is encountered, the preprocessor will go recursively back into A.hpp. But this time since INCLUDED_FROM_B_HPP is defined, it outputs the code contents of A.hpp.
Clear the definition of INCLUDED_FROM_B_HPP.
Output the definitions of inline members of B from the second part of B.hpp.
Option 3: friend class B;
Instead of specifying just the one member function B::geta to friend, just befriend the class itself, with the declaration friend class B;. Now A.hpp doesn't need to include B.hpp, so there's no circular dependency issue.
This doesn't much decrease encapsulation from the point of view of what access is and isn't possible, since normally any programmer who can modify any part of class B can also modify B::geta. But it does open possibilities of "accidentally" using non-public members of A in other members of B.
Option 4: Refactor access method
A.hpp
#ifndef A_HPP
#define A_HPP
class B;
class A
{
protected:
int a;
public:
A();
~A(){};
class AccessForB {
private:
static int geta(A& aobj) { return aobj.a; }
friend class ::B;
};
};
inline A::A()
{
a = 2;
cout << a;
}
#endif
B.hpp
...
inline void B::geta(A& ao)
{
b = A::AccessForB::geta(ao);
cout << b;
}
This code introduces a new sort of encapsulation: now class B can only get the value from member a, can't modify that value, and can't access any other non-public members of A. Additional accessors could be added for other members as appropriate. To permit modifying a member, the class could either provide "set" accessors, or an accessor that returns a reference. For non-public functions, the class could provide wrapper functions that just pass through to the actual function.
It's still true that it's possible for members of B other than B::geta to exploit the friendship, but now typing out A::AccessForB:: can't really be considered an accident.
... but I need them in separate files.
Move the inlined functions out to a separate B.cpp file that #include's A.hpp.
As being just seen as a forwarded class declaration A's declaration isn't yet complete at the point you're starting to use it in B.hpp, and the compiler complains about that righteously.
You can still retain the inline keyword, the compiler will respect it as a hint as usual.
Here's the sketch:
B.hpp
#ifndef B_HPP
#define B_HPP
using namespace std;
class A;
class B
{
protected:
int b;
public:
B();
~B(){};
void geta(A& ao);
};
#endif
B.cpp
#include "B.hpp"
#include "A.hpp"
inline B::B()
{
b = 1;
cout << b;
}
inline void B::geta(A& ao)
{
b = ao.a; // <<<<<<<<<<<< here's the problem to be solved
cout << b;
}
These questions and answers are very much related to your problem:
Resolve build errors due to circular dependency amongst classes
Why are C++ inline functions in the header?
C++ inline member function in .cpp file

Circular Inclusion and Inheritence with Forward Declarations Leads to C2504 base class undefined

I am getting a C2504 compilation error in PlayerController.h saying that my base class (Updateable) is undefined. I have searched for several hours for a solution to a circular inclusion with inheritance problem and their solutions are to remove the circular inclusions and jsut use a forward declaration. As far as I understand, this works if no methods from the forward declared class are called. However, in my program my Updateables class calls a method on its member inherited gameObject object and the GameObjects also call methods on their member Updateables. Because of this, Updateables need to include GameObject.h and GameObjects need to include Updateables.h. This leads to a C2504 in PlayerController.h saying that the base class Updateable can not be found.
Here are my relevant classes:
Component.h
#pragma once
#include "Vector3.h"
class GameObject;
class Component {
public:
GameObject* gameObject = nullptr;
Component();
};
Component.cpp
#include "Component.h"
Component::Component() {}
Updateable.h
#pragma once
#include "Component.h"
#include "GameObject.h"
class GameObject;
class Updateable : public Component {
public:
~Updateable();
virtual void update() = 0;
};
Updateable.cpp
#include "Updateable.h"
Updateable::~Updateable() {
if (gameObject) {
gameObject->removeUpdateable(this);
}
}
GameObject.h
#pragma once
#include "Updateable.h"
#include "GameManager.h"
class Updateable;
class GameObject {
public:
GameObject();
~GameObject();
void runUpdateables();
void addUpdateable(Updateable* updateable);
void removeUpdateable(Updateable* updateable);
private:
vector<Updateable*> updateables;
};
GameObject.cpp
#include "GameObject.h"
GameObject::GameObject() {
updateables = vector<Updateable*>();
GameManager::addGameObject(this);
}
GameObject::~GameObject() {
GameManager::removeGameObject(this);
}
void GameObject::runUpdateables() {
for (unsigned int i = 0; i < updateables.size(); i++) {
updateables[i]->update();
}
}
void GameObject::addUpdateable(Updateable* updateable) {
updateables.push_back(updateable);
updateable->gameObject = this;
}
void GameObject::removeUpdateable(Updateable* updateable) {
auto it = find(updateables.begin(), updateables.end(), updateable);
if (it != updateables.end()) {
updateables.erase(it);
}
}
PlayerController.h
#pragma once
#include "Updateable.h"
//#include "GameObject.h"
#include "Input.h"
class Updateable;
class PlayerController : public Updateable {
public:
float speed = 5.0f;
void update();
};
PlayerController.cpp
#include "PlayerController.h"
void PlayerController::update() {
float x = 0;
if (Input::getKeyDown(GLFW_KEY_A)) {
x = -speed;
}
if (Input::getKeyDown(GLFW_KEY_D)) {
x = speed;
}
cout << x << endl;
gameObject->getRigidBody()->velocity.x = x;
//yes this is a method in GameObject that I removed from this post
//because it would take up more space, rigidbody.h does not create
//a circular dependency
}
GameManager.h
#pragma once
#include "GameObject.h"
#include "PlayerController.h"
class GameManager {
public:
static void init();
static void addGameObject(GameObject* go);
static void removeGameObject(GameObject* go);
static void onFrame();
private:
static vector<GameObject*> gameObjects;
static GameObject* box;
GameManager.cpp
#include "GameManager.h"
vector<GameObject*> GameManager::gameObjects;
GameObject* GameManager::box;
void GameManager::init() {
gameObjects = vector<GameObject*>();
box = new GameObject();
box->addUpdateable(new PlayerController());
}
void GameManager::addGameObject(GameObject* go) {
gameObjects.push_back(go);
}
void GameManager::removeGameObject(GameObject* go) {
auto it = find(gameObjects.begin(), gameObjects.end(), go);
if (it != gameObjects.end()) {
gameObjects.erase(it);
}
}
void GameManager::onFrame() {
for (unsigned int i = 0; i < gameObjects.size(); i++) {
gameObjects[i]->runUpdateables();
}
}
Here is the exact error message: Error C2504 'Updateable': base class undefined Basic Platformer c:\users\default.sixcore-pc\documents\visual studio 2015\projects\basic platformer\basic platformer\playercontroller.h 9
A lot of your files have both #include "Class.h" and class Class; declarations. You never need both; use one or the other.
A definition of a class X must be visible when:
accessing the members of X
creating an object of type X
defining a class derived from X
using X as a template argument to a template which requires the corresponding template parameter to be a complete type (such as what standard library containers require of their element type). Note that this applies when using X, not X*.
In other cases (such as creating a pointer to X or declaring a function taking of returning X), a non-defining declaration (class X;) is enough.
Using these rules (plus moving function bodies from headers to source files when necessary), you can solve any circular dependency issues.
To directly address your files as presented:
Updateable.h does not need to #include "GameObject.h". It doesn't even need the forward declaration of GameObject.
GameObject.h doesn't need any of the two #includes in it.
GameManager.h doesn't need any #includes. It needs a declaration of class GameObject; though.
Descendant class must know the full definition of the base class. Forward declaration is not enough and useless.

Access to class which is only in cpp file of parent

I want to call a class which is only in the file of a parent source class file. In fact I have 3 classes in 4 files:
parent.h
parent.cpp
child.h
child.cpp
The "main" classes are Child and Parent. The class Otherclass is in the parent.h file above the definition of the Parent class.
How can I get access to the class Otherclass which is only in the parent.cpp file in the child.cpp file?
(Unfortunately I'm not allowed to make big changes in the parent files.)
parent.cpp:
using ParentNamespace::Parent;
namespace other
{
class Otherclass
{
public:
Otherclass()
{
// do something
}
~Otherclass()
{
}
};
}
Parent::Parent()...
...
// here the Parent class continues normal
child.cpp:
#include "parent.h"
Child::Child() :
ParentNamespace::Parent()
...
...
...
// here I want to use Otherclass
How can I get acess to the class 'Otherclass' which is only in the parent.cpp file in the child.cpp file?
You can't. This is the entire purpose of header files. Use them.
(Unfortunately i'm not allowed to make big changes in the parent files.)
Either the existing code is completely broken and you should use this fact to become allowed…
…or these are internal classes that you shouldn't be trying to use in this way.
You can always create a separate header file for OtherClass, copy the OtherClass definition (all the code you would usually out into the header, not the code of non-inlined functions) there and #include this header into child.h. It is not very bad to have several definitions of the same class as long as you are absolutely sure that they will be identical. It is not also a right way to do, but if you can not move the OtherClass definition to (some) header file, then you can copy it to a new header.
Although of course the first question to ask is why at all the existing code is done this way. Maybe OtherClass is just an implementation detail of Parent that may change in future development and which you are not supposed to use.
An example code (not exactly for your case, but illustrates how you can work without any header files at all):
// a.cpp
#include <iostream>
class A{
public:
int x;
A(int);
};
class B {
public:
int y;
B(int);
};
A::A(int v) {
std::cout << "A::A " << v << std::endl;
}
// b.cpp
#include <iostream>
class A{
public:
int x;
A(int);
};
class B {
public:
int y;
B(int);
};
B::B(int v) {
std::cout << "B::B " << v << std::endl;
A a(v+10);
}
// main.cpp
class A{
public:
int x;
A(int);
};
class B {
public:
int y;
B(int);
};
int main() {
A a(10);
B b(20);
}
builds and works as expected. However, it would be really difficult to maintain all the definitions identical, so that's what headers are for.

Header files and multiple class usage (EDIT: forward declarations)

I have a problem where I have several header files, and I need to include each of them in each other. Obviously, this cannot be done, because when I compile, the error "include nested too deeply" is thrown - as this essentially asks the compiler to enter an infinite include loop.
I could fix it using void pointers, but this seems like bad coding practice to me.
Here is an example of what I am trying to do, to aid understanding:
File-A:
#include "File-B"
#include "File-C"
class A
{
public: B* p_B;
public: C* p_C;
};
File-B:
#include "File-A"
#include "File-C"
class B
{
public: A* p_A;
public: C* p_C;
};
File-C:
#include "File-B"
class C
{
public: B* p_B;
};
This just shows where each class declaration is needed. Surely there is a better solution to void*.
EDIT: I am already using include guards, this code is just to help you see what I am trying to do.
You should use include guards:
#ifndef _FILE_A_H_
#define _FILE_A_H_
// Contents of FileA.h...
#endif
Possibly, also use forward declarations to break cyclic dependencies between the definitions of your data structures.
In FileA.h:
class B; // No need to #include "FileB.h"
class A
{
public:
B* pB;
};
In FileB.h:
class A; // No need to #include "FileA.h"
class B
{
public:
A* pA;
};
If you are using pointers or references to the other classes, and no code in the header file, you can use forward declarations:
class A; // Forward declaration
class C; // Forward declaration
class B
{
public:
A* p_A;
C* p_C;
};
If code in the header file refers to any members of the other classes, you will have to include the entire definitions of the other classes.
I would use include guards, which only include a certain file once.
#ifndef FILE_A
#define FILE_A
class A
{
public: B* p_B;
public: C* p_C;
};
#endif
http://en.wikipedia.org/wiki/Include_guard
It only includes the header file once per file.
You can also use #pragma_once, although it is not standard.
In the case that doesn't work, you can use a forward declaration.
class B;
class C;
class A
{
public: B* p_B;
public: C* p_C;
};
This is why you have #include <> guards.
#ifndef _FILE_B
#define _FILE_B
#include "File-A"
#include "File-C"
class B
{
public: A* p_A;
public: C* p_C;
};
#endif

Two classes and inline functions

I have two classes and both of them uses some of the other class, on example:
// class1.h
class Class1;
#include "class2.h"
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class2;
#include "class1.h"
class Class2 {
public:
static Class1 *C1;
...
};
And when I define it like in example above, it works (I also have some #ifndef to avoid infinite header recurency). But I also want to add some inline functions to my classes. And I read here that I should put definition of inline function in header file, because it won't work if I'll put them in cpp file and want to call them from other cpp file (when I do it I get undefined reference during linking). But the problem here is with something like this:
// class1.h
...
inline void Class1::Foo() {
C2->Bar();
}
I get error: invalid use of incomplete type ‘struct Class2’.
So how can I do it?
You need to delay including the header, but then include it and define your inline methods. By doing this in each header, they are self-sufficient and including one will always include the other, with include guards preventing infinite recursion.
A.hpp
#ifndef INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
#define INCLUDE_GUARD_B9392DB18D114C1B8DFFF9B6052DBDBD
struct B;
struct A {
B* p;
void foo();
};
#include "B.hpp"
inline
void A::foo() {
if (p) p->bar();
}
#endif
B.hpp
#ifndef INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
#define INCLUDE_GUARD_C81A5FEA876A4C6B953D1EB7A88A27C8
struct A;
struct B {
A* p;
void bar();
};
#include "A.hpp"
inline
void B::bar() {
if (p) p->foo();
}
#endif
You have it mix'd up. What you want is:
// class1.h
class Class2;
class Class1 {
public:
static Class2 *C2;
...
};
// class2.h
class Class1;
class Class2 {
public:
static Class1 *C1;
...
};
And include the respective headers in the source. The line:
class Class1; // or Class2
Declares an incomplete type, and you can have pointers and references to incomplete types. Upon usage, though, it needs to be complete. So just say "hey it'll exist!" in the header, and in the source tell it what it is.
My suggestion is that you place common methods and members into a base class, then derive C1 and C2 from the base class. This may fix the circular dependency issue.