Wrong use of forward declaration? - c++

Sometimes I use foreward declaration for nested classes:
class A;
class B
{
private:
A* object_A;
public:
B(){}
};
The question: What happens if I now use forward declaration of class B (B is declared and defined at this point) for the useage in class C? Does this cause any problems with class B, because it is defined (with implementation of methods etc.) but is used with forward declaration for class C? Does the syntax class B; in the following code-snippet overwrites somehow the previous declared, defined and implemented class B?
class B;
class C
{
private:
B* object_B;
public:
C(){}
};

Does the syntax class B; in the following code-snippet overwrites somehow the previous declared, defined and implemented class B?
Forward declarations are not about overwriting. It is just giving hint to the compiler that the type definition is implemented somewhere. For user defined pointer types, compiler does not require the definition but needs to know what is the type of the object.

Related

why declaring an object of a class before defining it gives error in friend class but not in friend function

class B;
class A {
private:
int numA;
public:
A(): numA(12) { }
// friend function declaration
friend int add(A, B);
};
this does not give any error on declaring object of class B in friend
function,,but this gives,,as firstly class B is declared
class Apple;
class B {
private:
int b;
public:
void showA(Apple d)
{
// Since B is friend of A, it can access
// private members of A
cout << "A::a=" ;
}
};
};
this gives an error of incomplete type for object d,,why this is happening though we already declared class apple before,
Why does the first example compile?
In your first example, you have a forward declaration of class B followed by a declaration of a friend function that uses it in its parameter list:
class B;
class A {
...
friend int add(A, B);
};
This is allowed because, although B is incomplete, we are not defining add yet, only declaring an intention to eventually do so.
Why does the second example not compile?
In the second example, we have a forward declaration of class Apple, followed by a definition of showA:
class Apple;
class B {
...
void showA(Apple d)
{
...
}
};
This time, since we are defining the function, the compiler is obligated to generate code for it. But because Apple is incomplete, the compiler cannot know, for example, how much space in memory to reserve to hold the parameter d. Therefore this is an error.
The question When can I use a forward declaration? explains some of what can and cannot be done with an incomplete (forward-declared) type.
The use of 'friend' is irrelevant here
The friend keyword is basically irrelevant here. friend primarily affects access control (in the sense of public and private), but that's not the issue here.
A detail: friend also affects scoping. Because of friend, add is not a member of class A, but rather refers to a member of the global scope without actually introducing one (it's weird). But that does not change whether an incomplete type can be used as a parameter.

C++ class object inside another class problem

I working on a project and I have a lot of classes that have instances of other classes as fields. The problem is that I must declare the classes in a specific order in order for the code to compile. Example below:
class A{
public:
B* b; //unknown type name B
A(){
b = new B();
}
};
class B{
public:
B(){
}
};
The code above does not work, because it says that B is unknown.
But, if I declare class B before A
it's working fine.
class B{
public:
B(){
}
};
class A{
public:
B* b; //Works perfectly
A(){
b = new B();
}
};
In my project, there's no way to re-arrange the classes in order for the error to go away.
Is there a way to bypass this error?
In my project, there's no way to re-arrange the classes in order for the error to go away. Is there a way to bypass this error?
You are describing a circular dependency. X depends on Y and Y depends on X. Such dependency is unsolvable. If you can remove a dependency on one class from another class, then it may be possible to re-order the definitions so that all dependencies are satisfied. Sometimes dependency can be removed by introducing indirection.
Note that just because one class definition (A) depends on declaration of another class (B), that doesn't necessarily mean that it depends on the definition of that class. You can have one class depend on the definition of another class, while still having the dependee class depend on the declaration of the depender.
Furthermore, just because definition of a member function (A::A) depends on definition of another class (B), that doesn't necessarily mean that the class (A) has that same dependency. This is because it is not necessary to define member functions within the class definition.
For example, your example class A does not depend on the definition of B. As such, A can be defined before B:
// declaration of B
// not a definition
class B;
// definition of A
class A{
public:
B* b; // depends on declaration of B
// does not depend on the definition
A();
};
// definition of B
class B{
public:
B(){
}
};
// definition of A::A
// does depend on definition of B
A::A() {
b = new B();
}

How to pre-declare a typedef class in C++

For example, class A has a member of class B. In general, for the purpose of minimizing compilation dependency, we often make class A include B's pointer, and pre-declare class B in the class A's declaration. Looks like this:
//B.h
class B
{
....
};
//A.h
class B;
class A
{
B*b;
A();
...
};
//A.cpp
#include "B.h"
A::A()
{
b=new B();
...
};
But now I have a question: if the class of B is defined using typedef like this:
typedef class
{
....
}B;
The previous pre-declared method will not work in this case. How should I pre-declare the class B in A.h?
In the code typedef class { .... } B; , it is an unnamed class, with B being a type alias for the unnamed class.
It is not possible to declare an unnamed class without defining it (i.e. providing the class body); and it is not possible to declare that B is a typedef for an unnamed class.
There is no such thing as a forward declaration of a typedef. In general a typedef can declare an alias for incomplete type that is completed later, but an unnamed class cannot fill either of those roles.
Removed further advice in response to voter feedback
Note: the question used the term "pre-declare". The C++ Standard does not use the terms "pre-declare" or the more common jargon "forward-declare". In the standard's terminology, a forward declaration of a class is simply called a class declaration. This can be clarified by saying "declaration that is not a definition" if it is not clear from context already.

C++ class methods forward declaration

Is there any way to redeclare a class to define methods which where only declared this far?
Eg. something like:
class A
{
void a();
void b() {}
}
class A
{
void a() {}
}
instead of
class A
{
void a();
void b() {}
}
A::a() {}
The reason is I created a lot of code with methods defined inside the class defintion, without using headers. I do not had cyclic references up to now, but recently there is need to. I don't like to define bunches of methods by the Type::method syntax, as only very few methods have to be known before the latter definition of the class.
So I like somewhat like a backward declaration, declare or define only a few methods before for cyclic references and define the whole class later.
No, there is no way to redefine a class.
According to the C++ language standard the class definitions is:
class-specifier:
class-head { member-specification_opt }
The standard explicitly says that member specification should be complete within class definition:
Members of a class are data members, member functions (9.3), nested types, and enumerators. The member-specification in a class definition declares the full set of members of the class; no member can be added elsewhere.
Also the standard gives example of redefinition of class:
struct S { int a; };
struct S { int a; }; // error, double definition
is ill-formed because it defines S twice.
Unfortunately there is no way to declare the class again once it is Closed with }.
Only thing you can do is you can inherit and define the method.
class B : public A { a() {} } ;

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 ?