Array:
#ifndef ARRAY_H
#define ARRAY_H
#include <bits/stdc++.h>
using namespace std;
namespace Maifee{
class Value;
class Array {
public:
Array();
vector<Value> _elements;
};
}
#endif // ARRAY_H
Object :
#ifndef OBJECT_H
#define OBJECT_H
#include <bits/stdc++.h>
#include "value.h"
using namespace std;
namespace Maifee{
class Value;
class Object{
public:
Object();
map<string, Value> _members;
};
}
#endif // OBJECT_H
Value :
#ifndef VALUE_H
#define VALUE_H
#include <bits/stdc++.h>
#include "array.h"
#include "object.h"
using namespace std;
namespace Maifee{
class Array;
class Object;
class Value {
public:
Value();
Value(Object *__object);
Array *_array;
Object *_object;
};
}
#endif // VALUE_H
I'm learning C++ at my best. With my teeny tiny knowledge in C++, I am trying to write some code. First reason I'm moving C++, pointers take a lot's of time.
Here I'm writing these code, where forward-declaration is necessary, and due to this even after using forward-declaration and ifndef, I need to use pointer, which I really don't want.
Can anyone really help me with this, how can I remove circular dependency??
Do I need to go back to C?
When using pointer I faced many problems such as, I have just one key-value pair in my map, but in the next line size becomes a very large number, out of nowhere.
Code inside main :
Object object=Object();
cout << "pop obj tem len" << object._members.size() << endl; //gives 0 as expected
object._members = members;
cout << "pop obj tem len" << object._members.size() << endl; //gives the expected number
Value val=Value(&object);
cout << val._object->_members.size() << "size here" << endl; //gives a random number
Constructor for Value with Object parameter :
Value::Value(Object *__object)
{
Object object;
object._members.insert(__object->_members.begin(), __object->_members.end());
_object = &object;
}
You can't avoid the forward-declarations and pointers in this situation.
class Object
has amap<string, Value>
member, andclass Array
has avector<Value>
member. Which meansValue
must be a fully-defined, complete type by the timeObject
andArray
are being compiled, asmap
andvector
need to know the total size of their element types. IfValue
were to have non-pointerArray
andObject
members, thenObject
andArray
would needValue
to be a complete type, butValue
would needObject
andArray
to be complete types. Catch-22!So, you have to use forward declarations and pointers/references for the
Value
members in order to make this kind of circular referencing work properly, since pointers/references to incomplete types are allowed.UPDATE: In your
Value
constructor that takes anObject*
parameter, you are setting the_object
member to point at a localObject
instance that goes out of scope and is destroyed when the constructor exits, thus leaving_object
dangling. That is why the subsequentval._object->_members.size()
expression inmain()
produces garbage (you are lucky the code didn't crash outright) -val._object
is pointing at invalid memory, so itsmembers
is not a validmap
object and so reading itssize()
is undefined behavior. That goes right back to the original comment I posted:To solve this, depending on your actual design goal, the
Value
constructor needs to either:Object
dynamically, which will have to bedelete
'd later. You will also have to provide a proper copy constructor and copy assignment operator:Object*
pointer it is given: