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 Objecthas amap<string, Value>member, andclass Arrayhas avector<Value>member. Which meansValuemust be a fully-defined, complete type by the timeObjectandArrayare being compiled, asmapandvectorneed to know the total size of their element types. IfValuewere to have non-pointerArrayandObjectmembers, thenObjectandArraywould needValueto be a complete type, butValuewould needObjectandArrayto be complete types. Catch-22!So, you have to use forward declarations and pointers/references for the
Valuemembers in order to make this kind of circular referencing work properly, since pointers/references to incomplete types are allowed.UPDATE: In your
Valueconstructor that takes anObject*parameter, you are setting the_objectmember to point at a localObjectinstance that goes out of scope and is destroyed when the constructor exits, thus leaving_objectdangling. That is why the subsequentval._object->_members.size()expression inmain()produces garbage (you are lucky the code didn't crash outright) -val._objectis pointing at invalid memory, so itsmembersis not a validmapobject 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
Valueconstructor needs to either:Objectdynamically, 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: