Class with a std::vector of another class objects - c++

I have two classes ( A and B)
I need to do something that when I make an object of class A (i.e. A obj()) a vector of class B that points to the objects of class A be constructed.
i.e.
if I make an object of class A named obj(), then I want the first element of vector in class B (i.e. vector<'A*'> objects ) to be declare by obj().
objects[0] = obj()
The code:
class B;
class A
{
public:
A(int _location)
{
location = _location;
pointer_B->redefine(this); // here in this line(14) I get two errors
}
private:
int location;
B* pointer_B;
};
class B
{
public:
void redefine(A* cur_obj)
{
objects.push_back(cur_obj);
}
private:
vector<A*> objects;
};
the errors are:
use of undefined type B (line 14)
left of '->redefine' must point to class/struct/union/generic type (line 14)

As #IgorTandetnik pointed out in the comments you have circular dependency between the class A and B. The solution is to separate the declarations and definitions either to header-source files and include the headers accordingly or put the definition of functions after the declaration of classes in the same translation unit.
class B;
class A
{
public:
A(int _location);
// .... other declarations
};
class B
{
public:
void redefine(A* cur_obj);
// ...
};
// definitions
A::A(int _location) {
location = _location;
pointer_B->redefine(this);
}
void B::redefine(A* cur_obj) {
objects.push_back(cur_obj);
}
Other remarks:
The member pointer_B is un-initialized in the constructor of
A. This is bad because it will lead to undefined
behaviour.
Hence initialise appropriately before dereferencing it.
Always prefer member initializer
lists
to initialize the class members: Read more in the following post: Why should I prefer to use member initialization list?
That means, change to:
class A
{
public:
explicit A(int _location, B *obj);
//^^^^^^^ ^^^^^^^^^
....
}
A::A(int _location, B *obj)
: location{ _location }
, pointer_B{ obj }
{
pointer_B->redefine(this);
}

```
class B;
class A
{
public:
A(int _location);
private:
int location;
B* pointer_B;
};
class B
{
public:
void redefine(A* cur_obj)
{
objects.push_back(cur_obj);
}
private:
vector<A*> objects;
};
A::A(int _location)
{
location = _location;
pointer_B->redefine(this);
}

Related

Why Friend Function cannot access private members of a class

class A{
public:
void printer(){
B obj;
obj.private_data = 10; // <- fails, says member inaccessible
}
}
class B{
friend void A::printer();
private:
int private_data;
}
is it possible for printer function to access private members of class B? i tried to pass an obj of B as arg to printer but it still failed
Class A doesn't know about B to use it. Hence, postpone the definition of the function printer() until you define B, and if you need an instance of B to be a member var in A then make a forward declaration for B to declare a B* in A.
Hence, use something like what follows:
class A {
public:
void printer();
};
class B {
friend void A::printer();
private:
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10; // <- No longer fails
std::cout << obj.private_data;
}
int main() {
A a;
a.printer();
}
Demo
Why Friend Function cannot access private members of a class?
They can, but you may need to split the definition of the class up a bit.
Imaginary files added:
Define A (file a.hpp):
class A {
public:
void printer();
};
Define B (file b.hpp):
#include "a.hpp" // B must see the definition of A to befriend a member function
class B {
friend void A::printer();
private:
int private_data;
};
Define A's member function (file a.cpp):
void A::printer() {
B obj;
obj.private_data = 10;
}
To access B, you first need to define it. Thus, you can just declare the method printer and define it after you have defined the class B.
class A {
public:
void printer();
};
class B {
private:
friend class A;
int private_data;
};
void A::printer() {
B obj;
obj.private_data = 10;
}
Note, you probably want to move your methods out of your class definition anyways and into a separate .cpp file. Methods defined inside the class are implicitly marked as inline which might not be what you expect.

Cyclic dependency involving global objects C++

So, I'm in this situation right now. I have two classes A and B. The B is subclass of A and there's also a global object of the B class which is initialized in the main. A function of the A class uses that global object and calls its functions. In what order do I have to write the declarations in order for the compiler to read everything?
I keep getting the same errors whatever I try. Namely:
- (x) does not name a type
- invalid use of incomplete type (x)
- forward declaration of (x)
Code example:
class B;
B* B_GLOBAL;
class A{
public:
void A_function(){
B_GLOBAL->B_function();
}
private:
};
class B : public A{
public:
void B_function();
private:
};
int main(void){
B_GLOBAL = new B;
return 0;
}
Move the definition of A_function below the declaration of B:
class B;
B* B_GLOBAL;
class A{
public:
void A_function();
private:
};
class B : public A{
public:
void B_function();
private:
};
void A::A_function(){
B_GLOBAL->B_function();
}
int main(void){
B_GLOBAL = new B;
return 0;
}

How can I deal with cyclic composition in C++?

I'm trying to create a cyclic composition in C++ but I'm dealing with declaration problems. How could I solve them?
This is an example, class A contains a vector of B objects, but class B needs A to be declared first because it's needed in its constructor:
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
In class A, you use object of class B, so the complete definition of class B is needed. To solve this, put class B definition above class A. At the same time, in class B you work only with pointer to A, so you don't need the complete definition of class A: declaration is enough there.
So, add forward declaration of class A above class B definition.
class A;
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};
You can forward declare pointer types:
class A; // sufficient to fully determine B
class B {
private:
A* parent;
public:
B (A* _parent) { parent = _parent; }
void some_method() {}
};
// now we have B defined, we can define A
class A {
private:
std::vector<B> sons;
public:
void create_son() {
B obj(this);
sons.push_back(obj);
obj.some_method();
}
};

forward declaration and typename using new keyword

I'm getting an error below in the class a declaring a new pointer of type b. Please help.
#include <iostream>
namespace B
{
class b;
}
class a
{
private:
B::b* obj_b;
public:
a(){}
~a(){}
void create()
{
b* obj_b = new b;
}
};
class b
{
private:
a *obj_a;
public:
b()
{
obj_a->create();
}
~b(){}
};
int main()
{
b obj;
return 0;
}
b* obj_b = new b;
And there is your problem. You can declare a pointer to a B because pointers are all the same size, but you cannot construct one or take one by value without providing the class definition to the compiler. How would it possible know how to allocate memory for an unknown type?
There were many errors in your code. These are related to forward declaration, fully qualified name usage etc.
namespace B
{
class b;
}
class a
{
private:
B::b* obj_b; // change 1 (fully qualified name)
public:
void create(); // change 2 (can't use b's constructor now as B::b is not
// yet defined)
a(){}
~a(){}
};
class B::b // change 3 (fully qualified name)
{
private:
a *obj_a;
public:
b()
{
obj_a->create();
}
~b(){}
};
void a::create() // definition of B::b's constructor visible now.
{
B::b* obj_b = new B::b; // And here also use fully qualified name
}
int main()
{
B::b obj;
return 0;
}

C++ referring to an object being constructed

In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing. So I'm trying to do something like this:
class A {
public:
A() : b(this) {}
private:
B b;
};
class B {
public:
B(A* _a) : a(_a) {}
private:
A* a;
};
Is there a way to ensure B always gets initialized with an A* without A holding a pointer to B?
Thanks
Try this:
class A;
class B {
public:
B(A *_a) : a(_a) {};
private:
A* a;
};
class A {
public:
A() : b(this) {};
private:
B b;
};
Since B is contained completely in A, it must be declared first. It needs a pointer to A, so you have to forward-declare A before you declare B.
This code compiles under more-or-less current versions of g++.
In C++ I have a reference to an object that wants to point back to its owner, but I can't set the pointer during the containing class' construction because its not done constructing.
You can store the pointer alright.
What you can't do is to try to get to the members/methods of A through the pointer in the constructor of B, since the parent instance might not be fully initialized at the point:
#include <iostream>
class Y;
class X
{
Y* y;
public:
X(Y* y);
};
class Y
{
X x;
int n;
public:
Y(): x(this), n(42) {}
int get_n() const { return n; }
};
X::X(Y* p): y(p)
{
//Now this is illegal:
//as it is, the n member has not been initialized yet for parent
//and hence get_n will return garbage
std::cout << p->get_n() << '\n';
}
int main()
{
Y y;
}
If you were to switch around the members in Y, so n would get initialized first, the constructor of X would print 42, but that is too fragile to depend on.