Declare an object even before that class is created - c++

Is there anyway to declare an object of a class before the class is created in C++? I ask because I am trying to use two classes, the first needs to have an instance of the second class within it, but the second class also contains an instance of the first class. I realize that you may think I might get into an infinite loop, but I actually need to create and instance of the second class before the first class.

You can't do something like this:
class A {
B b;
};
class B {
A a;
};
The most obvious problem is the compiler doesn't know how to large it needs to make class A, because the size of B depends on the size of A!
You can, however, do this:
class B; // this is a "forward declaration"
class A {
B *b;
};
class B {
A a;
};
Declaring class B as a forward declaration allows you to use pointers (and references) to that class without yet having the whole class definition.

You can't declare an instance of an undefined class but you can declare a pointer to one:
class A; // Declare that we have a class A without defining it yet.
class B
{
public:
A *itemA;
};
class A
{
public:
B *itemB;
};

There's an elegant solution using templates.
template< int T > class BaseTemplate {};
typedef BaseTemplate< 0 > A;
typedef BaseTemplate< 1 > B;
// A
template<> class BaseTemplate< 0 >
{
public:
BaseTemplate() {} // A constructor
B getB();
}
// B
template<> class BaseTemplate< 1 >
{
public:
BaseTemplate() {} // B constructor
A getA();
}
inline B A::getB() { return A(); }
inline A B::getA() { return B(); }
This code will work! So, why does it
work? The reason has to do with how
templates are compiled. Templates
delay the creation of function
signatures until you actually use the
template somewhere. This means that
neither getA() nor getB() will have
their signatures analyzed until after
both classes A and B have already been
fully declared. That's the magic of
this method.

Is this close to what you want: The first class contains the second class, but the second class (that is to be created first) just has a reference to the first class?

This is called cross reference. See here an example.

Related

Class Pointer reference inside of another Class defined below? (C++ 14, VS 2019)

Problem Summary
I'm attempting to write a series of classes in C++ 14, that are all supposed to be inside of the same class, and have pointer fields that point to object instances of each one of the classes. They are all also supposed to have constructors that assign those fields, using arguments that are pointers to the other class instances. I'm running into a problem where I am unable to call the constructor with the pointer arguments. Below is an illustration of my problem:
Defined in header file:
class A;
class B;
class C;
class A {
public:
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};
Runner code in cpp file:
A::C TEST_C = *new A::C();
A::B TEST_B = *new A::B(&TEST_C);
The line which initializes TEST_B with the constructor pointer argument call gives the following two errors in the VS 2019 compiler:
Error C2664 'A::B::B(C *)': cannot convert argument 1 from 'A::C *' to 'C *'
Error C2512 'A::B': no appropriate default constructor available
My Attempts
The first error line got me thinking that I may need to change my forward class declarations to include their respective parent classes too, as such:
class A;
class A::B;
class A::C;
However, that appears to break the reference to class C completely, and any references to it in the header above it's definition treat it as an undefined reference (Identifier "C" is undefined.). It's as if there were no forward declarations at all.
Adding A:: to each reference to class C in the rest of the header as such:
class A {
public:
class B {
public:
B(A::C* arg) {
ptr = arg;
}
A::C* ptr;
};
class C {
public:
...
};
};
didn't help either, instead the compiler tells me Class "A" has no member "C"..
However, one interesting thing that I did notice, was the fact that if I change the argument being passed to the constructor call for class B, to nullptr, that is:
A::B TEST_B = *new A::B(nullptr);
then the code gets compiled without problems. To me, that meant that this is most likely an issue with my forward class declarations, where the compiler sees that there are classes B and C declared, but it doesn't get to reading the actual content of the classes prior to attempting to reference them.
Is what I'm trying to accomplish here even possible with C++? Is there a way I should be doing this properly, that I'm not seeing?
Thank you in advance for reading my post, any help is appreciated!
The problem is that you've forward declared class C in global namespace instead of class scope A. This means that there are two different class named C one of which is declared to be in the global namespace ::C and the second one as an inner class A::C.
To solve this, just move the forward declaration of class C to inside class scope A as shown below:
header.h
class A {
public:
class C;// forward declaration moved here inside class scope A
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
};
};
Working demo
Also, be careful about other logical bugs like memory leak(if any) in your program.
class A {
public:
class C;
class B {
public:
B(C* arg) {
ptr = arg;
}
C* ptr;
};
class C {
public:
...
};
};

How can I define two inter dependant classes, preferably in the same header file?

So, I want something like:
class A{
B member;
};
class B{
A function();
};
No matter in which order I declare them, I get an incomplete type error (and I pretty much understand why).
How can I solve this? I don't want to use pointers or to have the function defined outside the B class. Also, declaring them before as
class A; class B;
doesn't seem to work either.
No need for class definition when declare a function.
class A;
class B{
A function();
};
class A{
B member;
};
This order will work:
class A;
class B {
A function();
};
class A {
B member;
};

How to create an instance of a nested class that is defined outside of the enclosing one?

If I define a nested class and then create an instance like this:
class A
{
class B
{
...
};
B b;
};
everything is ok. But if I just declare B inside of A and define it outside, I can't create an instance of B, probably because the compiler don't know how much space the instance of B will need. But code is not much readable when you define a class inside another. Is there a way to make this work?
class A
{
class B;
B b;
};
class A::B
{
...
};
Simple, just define class B, then define an instance of it in A.
class B
{
}
class A
{
B memberB;
}
Or you can forward declare it:
class B;
class A
{
B memberB;
}
class B
{
}
Truly nested classes are rarely needed and not very useful at all.
When you use a class type as a member, the concrete class needs to be known. That's why your second case doesn't work. A work around is to use pointer to B:
#include <memory>
class A
{
class B;
std::unique_ptr<B> b;
};
class A::B
{
};

Class prototyping

I have put several instances of class b in class a but this causes an error as class a does not know what class b is.
Now I know I can solve this problem by writing my file b a c but this messes up the reachability as well as annoys me. I know I can prototype my functions so I do not have this problem but have been able to find no material on how to prototype a class.
does anyone have an example of class prototyping in c++.
as there seems to be some confusion let me show you what i want
class A
{
public:
B foo[5];
};
class B
{
public:
int foo;
char bar;
}
but this does not work as A cannot see B so i need to put something before them both, if it was a function i would put A(); then implement it later. how can i do this with a class.
You can declare all your classes and then define them in any order, like so:
// Declare my classes
class A;
class B;
class C;
// Define my classes (any order will do)
class A { ... };
class B { ... };
class C { ... };
You're looking for declarations.
class A;
class B {
A MakeA();
void ProcessA(A a);
};
class A {
B bs[1000];
};
If you forward declare a class, you can
declare functions taking and returning it or complex types made of it
declare member variables of pointer or reference to it
This basically means that in any case which doesn't end up with instances of A inside B and vice versa, you should be able to declare and define any interface between A and B.
The usual way to resolve circular dependencies is to use a forward declaration:
// Bar.h
class Foo; // declares the class Foo without defining it
class Bar {
Foo & foo; // can only be used for reference or pointer
};
// Foo.h
#include <Bar.h>
class Foo {
Bar bar; // has full declaration, can create instance
}
You can provide a full declaration and definition in another file. Using the forward declaration, you can create pointers and references to the class, but you cannot create instances of it, as this requires the full declaration.
class b;
class a {
public:
b * inst1;
};
class b{
....
};
Is this what you needed ?

How to use class which defined below?

class A{
public:
B b;
};
class B{
public:
A a;
};
I can't write in A class "B b" because class B defined below. Is any way to make it work?
thanks
This is not possible. You need to use a pointer or a reference in one of the classes.
class B; // forward declare class B
class A {
public:
B * b;
};
class B {
public:
A a;
};
As to why it isn't possible: A contains a B contains an A contains a B ... There's no end to the recursion.
If you're used to languages (such as e.g. java) where all object variables are pointers/references by default, note that this is not the case in c++. When you write class A { public: B b; }; a complete B is embedded into A, it is not referred to within A. In C++ you need to explicitly indicate that you want a reference (B & b;) or a pointer (B * b;)
Think about it: Inside an object of class B there's an object of class A, and inside it there's an object of class B. This is physically impossible! What will be the size of object B?
sizeof(B) > sizeof(A) > sizeof(B)
You must use pointers, like the other answer suggested.
There is no way to make it work. You should use forward declaration and a pointer to one of the class
class B;
class A{
public:
B *b;
};
class B{
public:
A a;
};
That is because when you're writing B b the compiler must know what B is. But if you make a forward declaration then compiler will know that B is some class and you will be able to create pointers and references of B.
Only if you change at least one of the two member objects to a pointer. You would be able to declare a member pointer to such an object by forward-declaring the other class, like this:
class B;
class A{
public:
B* pb;
};
class B{
public:
A a;
};
The reason for this:
The compiler needs to know how objects of each class (A and B) will be laid out in memory. This includes how much memory will be needed for each object. Since class members require an amount of memory that depends on their members, it follows that the compiler can only allow you to declare a class member if it has seen the declaration of that member's class first.
Pointers, on the other hand, always take up the same amount of memory. This is why it's enough for you to tell the compiler "B is a class; I want a pointer to B here". The "B is a class" part corresponds to the class B; line above, which is called a forward declaration.