I'm doing a small program, just to play with classes.
And I've made two classes, a and b.
I want to be able to access a in b and vice versa.
This is what I got so far:
#ifndef A_HH_
#define A_HH_
#include <string>
class b;
class a
{
private:
string aString;
b* bClass;
public:
a(){aString = "A";}
string getString(){return aString;}
string getBString(){return bClass->bString;}
};
#endif /* A_HH_ */
and b:
#ifndef B_HH_
#define B_HH_
#include <string>
class a;
class b
{
private:
string bString;
a* aClass;
public:
b(){bString = "B";}
string getString(){return bString;}
};
#endif /* B_HH_ */
I want to be able to access the pointer not just store it.
How can I do that?
The problem is that you use the bClass pointer in class a, for that you need the definition of class b. In this case this can be solved by simply including b.hh in a.hh. This simple solution will work as you're only declaring an a pointer (but don't access it) in the class b. A forward declaration is not enough, because it doesn't actually tells the compiler anything more than that the class b exist.
Oh, and you need to change the bClass->bString in a::getBString to bClass->getString(), as b::bString is private. And of course create an actual instance of b and assign it to bClass.
In short, to access members of a struct or a class, you need to meet two conditions:
the accessing element (class, method, ...) must have access "rights" to the referenced member
the definition of the struct/class must be available.
To overcome 1. you can either make the member public, or declare the accessing class or method as friend, or better use a getter method.
To overcome 2., you need to include the header of the referenced class.
You might use templating:
for a:
#ifndef A_HH_
#define A_HH_
#include <string>
#include "b.h"
class a
{
private:
string aString;
b* bClass;
public:
a()
{
aString = "A";
bClass = new b<a>;
}
string getString(){return aString;}
string getBString(){return bClass->getString();}
};
#endif /* A_HH_ */
and for b:
#ifndef B_HH_
#define B_HH_
#include <string>
template <typename T>
class b
{
private:
string bString;
T* aClass;
public:
b()
{
bString = "B";
aClass = new T;
}
string getString(){return bString;}
string getAString(){return aClass->getString();}
};
#endif /* B_HH_ */
This removes the circular dependency
Related
I've two different classes (class1 class2) both of them have their own header and cpp files. Class2 has included the header of class1. Class1 has two structures which are public.
I want to call a method from class2 in class1 and to pass two pointers pointing on the structures.
The call of the method from class2 in class1. (obj is an object of class2 in class1):
obj.routine(ip_s.c_str(), &NLP_data_recv, &recv_data_data); //write to harddrive
Following the declaration of the method in class2:
int routine(std::string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data);
The following Error occurs:
“argument of type ""com::NLP_data_data_package *"" is incompatible with parameter of type ""NLP_data_data_package *""
How can I solve this problem? Thank you.
EDIT: Additional code:
class com header(class1):
#ifndef COM_H
#define COM_H
//...
#include "Dateiverwaltung.h"
//...
class com
{
private:
Dateiverwaltung obj;
//...
public:
int run(void);
com(std::array<std::string,TWO> socket);
~com();
struct NLP_data_header_package
{
//...
}NLP_data_recv;
struct NLP_data_data_package
{
//...
}recv_data_data;
class com cpp (class1)
//...
if (recv_command == DATA_COMMAND)
{
obj.routine(ip_s.c_str(), &NLP_data_recv, &recv_data_data); //write to harddrive
obj.ext_close_file();
}
//...
class Dateiverwaltung header(class2)
#ifndef DATEIVERWALTUNG_H
#define DATEIVERWALTUNG_H
//...
#include "communication.h"
//...
public:
Dateiverwaltung(char* directory_global_re);
~Dateiverwaltung();
int routine(std::string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data);
int ext_close_file(void);
//...
class Dateiverwaltung cpp (class2)
//...
int Dateiverwaltung::routine(string raw_data_re, struct NLP_data_header_package *Header_data, struct NLP_data_data_package *Data_data)
{
//...
The error says there's a "com::NLP_data_data_package"
and a "NLP_data_data_package"
That's two different classes (for the compiler), since they seem to be defined in different namespaces, namely com and the default namespace.
I a beginner in programming.
I coded two classes(having constructors with requirement to pass arguments) and want to declare and use one class's object in another class.
I have tried to find the solution to my error on many website, but none of them worked. I also saw a solution to this problem using the 'new' syntax.
Please suggest some(any) way to sought out this problem.
A short program similar the one in which I am facing problems is as follows:
(I know this program is stupid but, this is not actual program I am facing problem in. Instead this is a narrowed down version of the part of the program in which I am facing error)
The error is in Class2.h and main.cpp
main.cpp
#include <iostream>
#include "Class2.h"
using namespace std;
int main()
{
Class2 Class2_Obj;
Class2_Obj.Class2_Function(); // error: undefined reference to `Class2::Class2_Function
return 0;
}
Class1.h
#ifndef CLASS1_H_INCLUDED
#define CLASS1_H_INCLUDED
class Class1
{
private:
const int c1_Variable;
public:
Class1(int);
// Displays the value of c1_Variable on output screan
void Class1_Function();
};
#endif // CLASS1_H_INCLUDED
Class1.cpp
#include <iostream>
#include "Class1.h"
Class1::Class1(int receivedInt) : c1_Variable(receivedInt) {}
void Class1::Class1_Function()
{
cout << c1_Variable;
}
Class2.h
#ifndef CLASS2_H_INCLUDED
#define CLASS2_H_INCLUDED
#include"Class1.h"
class Class2
{
private:
Class1 Class1_Obj(4); // 4 is just a random number.
//error: expected identifier before numeric constant
//error: expected ',' or '...' before numeric constant
public:
// Calls Class1_Function()
void Class2_Function();
};
#endif // CLASS2_H_INCLUDED
Class2.cpp
#include <iostream>
#include "Class1.h"
#include "Class2.h"
void Class::Class2_Function()
{
Class1_Obj.Class1_Function();
}
Here are the links to snapshots of the errors:
Screenshot of Error in Class2.h - http://i.stack.imgur.com/WpK9k.jpg
Screenshot of Error in main.cpp - http://i.stack.imgur.com/yDBD7.jpg
Please help me out! Thanks in advance for any responses :)
The issue is that this in-place initialization of non-static data members syntax is invalid:
class Class2
{
private:
Class1 Class1_Obj(4);
....
};
You can use {} instead,
class Class2
{
private:
Class1 Class1_Obj{4};
....
};
or this form
class Class2
{
private:
Class1 Class1_Obj = Class1(4);
....
};
C++ is a Object Oriented Language. It has classes to structure its data.
To put one class into another, you make an object of one class a member of another class.
Syntactically, it works like
class A {
int x;
public:
A (int x1) : x(x1) {}
};
class B {
A a; // this is how you do it ..
public:
B() : A(4) {}
};
B b; // b is an object which has a member b.a
As you can see, b is an object of class B. It has a member a of class A.
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) {}
};
Right now, my project has two classes and a main. Since the two classes inherit from each other, they are both using forward declarations. In the first object, right underneath the #include statement, I initialize two enums, before the class definition. I can use both enums just fine inside that class. However, if I try to use those enums in the other class, which inherits from the first one, I get an error saying the enum has not been declared. If I try to redefine the enum in the second class, I get a redefinition error.
I have even tried using a trick I just read about, and putting each enum in its own namespace; that didn't change anything.
Here's an example:
#ifndef CLASSONE_H
#define CLASSONE_H
namespace Player
{
enum Enum
{
One,
Two,
};
}
#endif
Then inside the second class, I attempt to use the enum declared earlier:
void AddPlayer(Player::Enum playerNumber);
and instead get an error saying 'Player' has not been declared.
I'm not sure what issue you are having without seeing your code, but this compiles:
enum OutsideEnum
{
OE_1,
OE_2,
};
namespace ns
{
enum NSEnum
{
NE_1,
NE_2,
};
}
class Base
{
public:
enum BaseEnum
{
BE_1,
BE_2,
};
void BaseFunc();
};
class Derived
{
public:
enum DerivedEnum
{
DE_1,
DE_2,
};
void DerivedFunc();
};
void Base::BaseFunc()
{
BaseEnum be = BE_1;
Derived::DerivedEnum de = Derived::DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
void Derived::DerivedFunc()
{
Base::BaseEnum be = Base::BE_1;
DerivedEnum de = DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
int main()
{
Base::BaseEnum be = Base::BE_1;
Derived::DerivedEnum de = Derived::DE_1;
OutsideEnum oe = OE_1;
ns::NEEnum ne = ns::NE_1;
}
Two things to watch for with enums defined inside a class definition:
Make sure it's declared public if you want it publicly available.
When referencing it from anywhere other than the class it's defined in, use the class name to qualify the name of the enum and the values.
EDIT:
Ok, the problem has nothing to do with enums, but rather order of inclusion, when you have a base class and a derived class, only the derived class needs to know about the base class:
Base class header:
#ifndef BASE_H
#define BASE_H
enum BaseEnum
{
};
class Base
{
};
#endif
Derived class header:
#ifndef DERIVED_H
#define DERIVED_H
#include "Base.h"
class Derived
{
void Func(BaseEnum be);
};
#endif
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.