Regarding forward declaration c++ class - c++

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!

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

identifier "xxx" is undefined, class pointer and struct

I am writing a small c++ - program containing a similar structure to the following:
class A {
B * someObjects;
};
typedef A* APointer;
struct B{
APointer a;
int n;
}
Trying to compile this gives a "identifier is undefined" error since struct B is not known inside class A. Otherwise declaring struct B before class A should still give a similar error, since then B does not know APointer, or APointer does not know A. Is there any possibility to make class A and struct B being good friends?
Thanks in advance!
You need to forward declare B as the compiler has no idea what B is when it is used in A. B is considered an incomplete type in A and you are allowed to have a pointer or reference to B in A. You can change your code to:
struct B;
class A {
B * someObjects;
};
typedef A* APointer;
struct B{
APointer a;
int n;
};
Have you ever heard the term Forward Declaration! Your compiler don't know about B yet. So give a declaration of B first.
struct B; // forward declaration
class A {
B * someObjects;
};
//... rest of the code

Ciclic class use inside another class

I have two classes inside one cpp file like this:
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public
B returnSomeB()
{
aReferenceToB->someFunction();
return *aReferenceToB;
}
};
class B
{
private:
A needed_Class_A_var;
public:
void someFunction()
{
return;
}
};
This ciclic use of these two classes, one inside another, generates all sort of errors like
error C2143: syntax error : missing ';' before '*'
How can I resolve this ciclic include problem without creating separate files for each class and using only one cpp file?
I have tried to add a class B; declaration before class A definition wich does not work properly.
Before you access members of the B class (aReferenceToB->someFunction()), or even try to return the object of B (not the pointer to B) (B returnSomeB), you need to have a complete definition of class B first.
So, just extract the returnSomeB body out of the class A definition, and put it in place where the full definition of B is known.
class B;
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public:
B returnSomeB();
};
class B
{
private:
A needed_Class_A_var;
public:
void someFunction()
{
return;
}
};
B A::returnSomeB(){
aReferenceToB->someFunction();
return *aReferenceToB;
}
Please note that if you try to write something like this:
class B;
class A
{
private:
int somethingPrivate;
B *aReferenceToB;
public:
B* returnSomeB() { return aReferenceToB; }
};
that would be valid, because you're only manipulating with the pointers here (in this case, you're not creating object of B, and you don't access any of B's members), and the size of the pointer is known at the compile time, even without class B definition.

Class reference to parent

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

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.