Class reference to parent - c++

i'm pretty new at using C++ and I'm actually stopped at a problem.
I have some class A,B,C defined as follow (PSEUDOCODE)
class A
{
...
DoSomething(B par1);
DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
The problem is :
How to make this? If I simply do it (as I've always done in c#) it gives errors. I pretty much understand the reason of this. (A isn't already declared if I add the reference (include) of B and C into its own header)
Any way to go around this problem? (Using void* pointer is not the way to go imho)

Forward-declare B and C. This way compiler will know they exist before you reach the definition of class A.
class B;
class C;
// At this point, B and C are incomplete types:
// they exist, but their layout is not known.
// You can declare them as function parameters, return type
// and declare them as pointer and reference variables, but not normal variables.
class A
{
....
}
// Followed by the *definition* of B and C.
P. S.
Plus, one more tip unrelated to the question (seeing how you come from a C# background): it's better to pass by const reference than by value:
class A
{
...
void DoSomething(const B& par1);
void DoSomething(const C& par1);
...
}

For function declarations, parameter types are allowed to be incomplete if the function is not defined there:
class B;
class C;
class A
{
...
R DoSomething(B par1);
R DoSomething(C par1);
...
}
class B
{
A parent;
...
}
class C
{
A parent;
...
}
inline R A::DoSomething(B par1) { ... }
inline R A::DoSomething(C par1) { ... }
So you just define them after B and C become complete. But since they are defined outside the class, make them inline so multiple definitions in different translation units won't cause linker errors.

You should forward declare classes B and C before A:
class B;
class C;
class A {
...
};
At the point where B and C are referenced within A, the compiler only needs to know what kind of animals these are. With the forward declaration you satisfy the compiler. Then later you can define them properly.

use forward declaration
You can define class A; without it's implementation, before B and C, and then define it later

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:
...
};
};

Regarding forward declaration c++ class

I have two classes like this:
class B;
class A {
public:
int a, b;
B *b;
public:
int getctxt()
{
b->getctxt1();
}
}
Class B {
public:
int c,d;
A *a;
getctxt1()
{
/* something */
}
}
main()
{
B *b = new B();
A *a = new A();
b->a = a;
a->b = b;
}
But when I try to compile, it says
invalid use of incomplete type ‘struct A’.
Can anyone tell me how to solve this?
Inline class member function definitions are parsed as if they appeared right after the class definition. Of course B isn't defined at that point. So move the member function definition for A::getctxt out of the definition of class A:
class B;
class A { int getctxt(); /* ... */ };
class B { /* ... */ };
int A::getctxt()
{
b->getctxt1(); // at this point, *b has complete type!
return -35;
}
This is the reason why it is recommended to separate your classes in a .h file and a .cpp file. When you write class B;, you are telling the compiler that there is a class called B, but that's it, the compiler does not know what is inside this class. When the compiler reaches the line b->getctxt1();, it knows that b is an instance of B, but it does not know if getctxt1() is a method of B, because that is below. If you are writing all in a single file, you should first write all the declarations, and then all the implementations.
didn't anyone notice Class B syntax error? lowercase class is correct.
and those two public members in A with the same name int b and B *b.
once you remove those and finish class definitions with semicolons, add a void type to the void getctxt1() that is missing it in B.
just define functions as they should be defined. not inline without a reason that you know which is!

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 ?

Want to pass objects as a parameter in member function c++

Hai
I have a class A,B,C now i have member function in class A which needs the objects of
class B,C. Is it possible to achieve. If yes how?
class A
{
public:
void fun(B obj_b,C obj_c)
{
}
}
class B
{
//some work
}
class C
{
//some work
}
int main()
{
B obj_b;
C obj_c;
A obj_a;
obj_a.fun(obj_b,obj_c); //I GET ERROR HERE DURING COMPILATION
}
What is wrong in the above code?.
ERROR:
note: synthesized method first required here
error: initializing argument 1 of ‘void A::fun(B,C)’
Thank you
If it's not a typo : Your function fun is ill-formed, the return type is missing.
void fun(B obj_b,C obj_c) // void was missing
{
}
And as other pointed, there are several other problem with this code as missing return type for main, missing ; for class definitions, class B and class C must be declared before class A...
This last one seems to be what your error says.
Might be because of class declaration..
At void fun(B obj_b,C obj_c) the compiler has no idea about class B and class C. So try giving like
class B
{
//some work
};
class C
{
//some work
};
class A
{
public:
void fun(B obj_b,C obj_c)
{
}
};
If the classes are in different header files, #include them in class A..
Hope it helps..
The classes B and C are unknown in the void fun(B obj_b,C obj_c) line, you have to declare them first.
Either declare and define them first, if this is not possible (e.g. because they also need A), you can use forward declarations. It's just two single lines
class B;
class C;
BTW: With the method declaration void fun(B obj_b,C obj_c) you pass the parameters per value, what means that the objects B and C are copied. Most of the time this is not what u want: Pass them by reference by changing the method signature to void fun(B& obj_b,C& obj_c) .
After you correct all the syntax errors, you may encounter an error for the line declaring the fun member function, saying that the classes B and C are not yet declared. Place a forward declaration for classes B and C before the A class declaration. That is, something like:
class B;
class C;
class A
{
public:
void fun(B obj_b, C obj_c)
... other stuff here
};
class B
{
... real declaration of the class B
};
class C
{
... real declaration of the class C
};
By the way, forward declarations are the only method of circularly-referenced class declarations.

Declare an object even before that class is created

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.