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
Related
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.
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) {}
};
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
Just read about friend functions and I'm trying to access private variable "number" in class A with friend function "Print" from class B. I'm working with Visual Studio. Compilation of my code gives me plenty of various errors like:
C2011: 'A' : 'class' type redefinition
C2653: 'B' : is not a class or namespace name
Please be patient with me me and show a proper way of achieving my goal.
Here are my files
A.h:
class A
{
public:
A(int a);
friend void B::Print(A &obj);
private:
int number;
};
A.cpp:
#include "A.h"
A::A(int a)
{
number=a;
}
B.h:
#include <iostream>
using namespace std;
#include "A.h"
class B
{
public:
B(void);
void Print(A &obj);
};
B.cpp:
#include "B.h"
B::B(void){}
void B::Print(A &obj)
{
cout<<obj.number<<endl;
}
main.cpp:
#include <iostream>
#include <conio.h>
#include "B.h"
#include "A.h"
void main()
{
A a_object(10);
B b_object;
b_object.Print(A &obj);
_getch();
}
... Second you might need a forward declaration of class B in the A.h header file to refer B as a friend:
#ifndef _A_H_
#define _A_H_
class B;
class A
{
friend class B;
};
#endif
UPDATE
I'm currently not so sure if it's possible to declare member functions as friends, I'll have a look.
It's not possible to create member function friend declarations, you can either declare global functions or whole classes as friend, see also: C++ ref, Friendship and inheritance.
In general it's not a good design idea to use friend at all, because it strongly couples the classes together. The better solution will be to couple interfaces (which don't need to be publicly visible anyways).
In rare cases it might be a good design decision but that almost always applies to internal details.
First you need to put
#ifndef A_H
#define A_H
.... your A-class definition
#endif
in your A.h and analogous in B.h, so that multiple includes of the same file is prevented (that is your duplicate definition error)...
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.