I have a basic question that has bothered me for sometime.
When using a Class within a Class I can define the header of the Class I want to use in the header file. I have seen two ways of doing this and would like to know the difference between the two methods?
ex1
#include "ClassA.h"
class ClassB {
public:
ClassB();
~ClassB();
ClassA* a;
};
#endif
ex2 Here is the other way of doing it. The ClassA Header would be defined in ClassB source file.
class ClassA;
class ClassB {
public:
ClassB();
~ClassB();
ClassA* a;
};
#endif
What are the differences with these two methods?
The comlpete layout of the classA is known to the compiler when you include the class definition.
The second syntax is called Forward declaration and now classA is an Incomplete type for the compiler.
For an Incomplete type,
You can:
Declare a member to be a pointer or a reference to the incomplete type.
Declare functions or methods which accepts/return incomplete types.
Define functions or methods which accepts/return pointers/references to the incomplete type (but without using its members)
But You cannot:
Use it as a base class.
Use it to declare a member.
Define functions or methods using this type.
Use its methods or fields, in fact trying to dereference a variable with incomplete type.
So Forward Declaring the class might work faster, because the complier does not have to include the entire code in that header file but it restricts how you can use the type, since it becomes an Incomplete type.
The second method only allows you to create pointers to ClassA, as it's size is unknown. It may however compile faster as the header for the full definition for ClassA is not included.
The latter is a forward declaration. This way you can declare a pointer or reference to a class, even though you have not yet fully declared it. This can be used to resolve cyclic dependencies. What if, in your first example, A also wants to use a pointer to B. This wouldn't work, because when A is declared, B is not known yet. To solve this, you can use a forward declaration to tell the compiler that there is a class B, and you will tell it later what it looks like.
Related
I am working with a GitHub library and ran across a derived class instantiation that perplexes me. In abbreviated form,
class A
{
public:
A() {}
int AFunc(void) { return(1); }
};
class B : public A
{
public:
B(void) : A() {}
int BFunc(void) { return(2); }
};
Within an include file, the class is instantiated as follows:
A &tObject = *(new B());
Sample code then refers to 'tObject' as global variable calling methods from class A and/or B.
For example:
tObject.AFunc();
tObject.BFunc();
So here's the question, is that instantiation legal?
The compiler is only fussing on the call to a service class's method, saying that class A has no such member. That error makes sense to me and I've narrowed the issue to the above explanation.
While I do not have broad compiler experience, I have been programming in C++ for many years. I've never seen such a construct.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
In my experience, I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct. Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
An insight is highly appreciated.
It cannot. The compiler is right to complain, there is no way this is valid. Remember that C++ is a static language, which means that the compiler will try to find a function named BFunc in A, which it cannot, as there is no such function.
This might be a compiler extension of some sort, but anyways, this isn't legal standard C++. Most probably, the author wanted to make BFunc a virtual method in A, which would have made the access legal.
Would someone kindly explain how an object declared, in my example, as 'class A' can access methods from the derived class B?
As explained, this cannot be.
I've always declared the derived class as a pointer and then accessed methods from the base or derived class using the '->' construct.
You can also do this with references, not just with pointers. Although this is done less often than pointers, so this might explain why you haven't encountered this yet.
Oftentimes, I've stored the derived class as a pointer to the base and then performed a cast to convert when or if I needed access to the derived class's methods.
Exactly, this is the correct way to access the derived class members. As then the compiler will know the type of the object and can actually find BFunc and call it. Now, if the type is not really a B, then you have undefined behavior, but yes, this is what one should do.
Also, please get your terminology right:
the class is instantiated as follows
If there are no templates involved, then there is no instantiation happening. The only thing you are doing here is declaring or more specifically defining a variable named tObject.
// The declaration of the reference as a reference to the base class is not a problem, and is actually performed in some STL implementations.
class A
{
};
class B : public A
{
public:
void f1() {}
};
int main()
{
A * a = new B; // You know its OK using pointers
A & a2 = *(new B); // Also OK, a2 is a reference for a place in memory which is-a-kind-of A
// a2.f1(); // Will not compile - compiler only knows for sure its of type A
((B&) a2).f1(); // This will work. There is really a B there
return 0;
}
I am making a project, which requires multiple classes, some of them are inherited!!
So i am using one inherited class in a main class before it's definition!
Kindly help me to how to use prototype declaration for inherited class.thanks!!
Example:
class A
{
/*data*/
};
class B:public A
{public:
void func()
{
C obj;
}
};
class C:public B
{
};`
Only functions have prototypes. What you can do with class is to forward declare it.
class MyFutureClass;
struct MyFutureStruct;
These is an incomplete classes. No, that structs in C++ are same as classes, just they have public access by default, classes have private. To make them complete you should provide definition anywhere further in code.
Incomplete class is just one possible incomplete type. The following types are incomplete types:
type void;
class type that has been declared but not defined;
array of unknown size;
array of elements of incomplete type;
enumeration type until its underlying type is determined.
Now what you can use incomplete class for?
declare a pointer variable or class field
Declare a function or method that accepts argument or returns of incomplete type, without defining it.
what you can't do with it?
Inherit incomplete class by other class
Define objects fields of incomplete type
Declare non-static class data member of incomplete type
Use incomplete class type as parameter for template
Define functions that use argument of incomplete type or
Perform implicit or explicit conversion to incomplete class, implicit or explicit, lvalue-to-rvalue conversions, standard conversion, dynamic_cast, or static_cast to pointer or reference of incomplete type, except when converting from the null pointer constant or from a pointer to void (void* always can be converted and void never is defined)
Access incomplete class' members or methods
Use new expressions that create object of incomplete type
Use it in catch-clause
Use typeid, sizeof, or alignof operator
Use arithmetic operator on pointer to incomplete class (because sizof isn't known , of course)
What it is needed for?
To avoid cyclic dependency of headers, when one class depends on existence and functionality of other
To reduce amount of headers included in single file. You can define class that got pointers and formal parameters of declared class without defining it
let's see, this is an absolutely useless example of avoid cyclic use of headers.
[class_a.h]
class B;
class A
{
B* p;
public:
A ( B& value );
};
[class_b.h]
#include "class_a.h"
class B : public A // we need complete A to inherit it
{
int a;
public:
B ( const B& );
};
[class_a.cpp]
#include "class_b.h"
// to define this constructor we need complete A, but header with complete
// definition is already included within class_b.h header
A::A ( B& val) : p( new B(val)) // we created copy of B
{
}
So, to define class A we need class B, but class B is child of class A, thus it needs complete definition of A. Conundrum? No. Thanks to forward declaration, we can define class A without defining B.
(PS. If someone reviewed code and found something impossible there, my explicit allowance to fix it is due... I'm falling asleep)
I have three classes that interact as follows. Class A contains a private member of type Class B. It also contains a method to which an object of type ClassC is passed. This method then calls a method on ClassC, passing to it a particular interface (ClassBInterface1) of its member of type ClassB:
ClassA
{
void Foo(ClassC ObjectC)
{
ObjectC.Bar((ClassBInterface1) ObjectB);
}
ClassB ObjectB;
}
My question is: ClassA does not need to access the methods of ClassB defined in Interface1. Therefore, in my view, it would be more elegant if the member of ClassA was of type ClassBInterface2, rather than ClassB. Is it possible to do this, while still passing B to C under Interface1?
The only way I can think of is to typecast ClassBInterface2 to ClassB and back to ClassBInterface1 in the Bar method in ClassA.
Is this the best way to do it? Or should I just leave it as it is?
Thanks a lot for any help.
If you define ObjectB as a ClassBInterface2 it won't be possible to convert it to ClassBInterface1 at runtime because it's internal structure won't be known.
Your way is the best one to do it but you can do a little modification. You don't need to do a explicit cast from ClassB to ClassBInterface1 while calling ObjectC.Bar because the compiler will do it for you.
If class B is defined as follows:
ClassB : public ClassBInterface1, ClassBInterface2
{
/*Class methods and attributes*/
}
you can just do the following while calling the Bar function on the ObjectC (assuming objectB is defined as ClassB)
ObjectC.Bar(ObjectB);
C++ has a great feature for this called "forward declarations". Basically, for any parts of your code that don't need to know the details of a class, you can simply pass around a reference. Only when you want to call member methods (including constructors and destructors) do you need to have the full class definition.
#include "ClassC.h"
class ClassB;
class ClassA
{
public:
void foo(ClassC& objectC)
{
objectC.bar(_objectB);
}
protected:
ClassB& _objectB;
};
Note that we include a header for ClassC because we need to call one of his methods.
Note that we forward declare ClassB and only hold a reference because we don't really care what he is.
Note finally that ClassA can't be instantiated currently, because somehow the reference to _objectB has to be set to something. For example, a constructor:
public ClassA(ClassB& objectB)
: _objectB(objectB)
{}
ClassA now only holds on to whatever reference was given to him on construction.
Based on your use of the term "interface" in your question, I assume you may have a class hierarchy. This answer can easily be extended to such a hierarchy. But the important point here is that concrete types always require a class definition, while simple reference object only require a forward declaration.
I have a class manipulating only shared_ptr to an inheritance hierarchy (quite simple, there are a few classes, say A, B, C etc. inheriting from a single class Base). Since I do not need to manipulate the instances of A, B, C... themselves, they are only forward declared. However, the compiler chokes when I try to pass a shared_ptr<A> to a method taking a shared_ptr<Base>, since the compiler does not know that A inherits from Base. Is there any other way than either static_pointer_castor #includethe header of class A? And if not, which one would you choose?
EDIT: adding some code
// in some file: (Base.h)
class Base
{
/*code*/
}
// in another file (A.h)
class A : public Base
{
}
// in my file (impl.cpp)
class A; // forward declaration
void Dummy()
{
std::shared_ptr<A> myPtr;
// we have somewhere: void sillyFunction(shared_ptr<Base> foo)
sillyFunction(myPtr); // does not compile, as no conversion is found.
}
Is there any other way than either static_pointer_castor #includethe header of class A?
No. In fact, the #include is the only way to do it properly (static_pointer_cast either wouldn't work or invokes undefined behavior). You can't cast ordinary pointers between incomplete subclass and superclass, either.
I have a simple code below:
class B;
class A{
B b;
};
class B{
public:
B(){
}
};
In class A's definition, I have a B-typed property. Using MS Visual Studio to compile, I've got the following error:
error C2079: 'A::b' uses undefined class 'B'
Due to some reasons, I can't put class B's definition before class A's one. Any idea?
The compiler is already telling you what's wrong : A has a member data b which is of an undefined type. Your forward declaration:
class B;
is just that : a declaration, not a definition. Since class A contains an instance of B directly (not just a pointer to B), the compiler needs to know the exact size of B : it needs its definition, not just a declaration, i.e. a promise that B will exist at some point.
The simplest thing to do here would be to reorder things this way:
class B{
public:
B(){
}
};
class A{
B b;
};
Edit : see also this question for the difference between declaration and definition.
Further edit : an alternative would be to change your member data to a pointer or a reference.
Do note that this isn't a trivial syntax change: it has implications on the life-cycle of your objects since the object pointed by A::b may then survive the destruction of A.
If what you want is composition (B is a part of A and dies with A), using a pointer will make your life harder with little benefits.
More edits(!) : just realized I misread the end of your question; what are the reasons preventing you from declaring B before A ?
If they cannot be worked around, you may have to go the pointer route. These reasons might be a sign that your objects are too tightly coupled though ! (perhaps B needs to be an inner class of A ? Or simply be merged into a single object ?)
class A;
class B {
A * getA();
};
class A {
B b;
};
This is the typical way to solve this. You must have B's definition in order to have a B b; member.
You need a forward declaration in order to declare a reference/pointer to B, you need the full definition in order to do anything else with B (such as defining a variable, calling a member function and so on)
You can do what you wish if you change the reference to b into a pointer to B.
class A{
B* bPtr;
};
class B{
public:
B(){
}
};
In principle, you don't need an explicit declaration - that is, a forward declaration is all that is needed - when you don't need the actual size of the class, or access to the types and member functions inside the class.
In your original example, you are making a direct reference to B. As a result, the compiler needs to know everything about B, thus requiring an explicit declaration instead of a forward one.
By having your A class declaration using a pointer to B, then you can get away with a forward declaration.
edit
Some links might explain the concept for you:
http://www.goingware.com/tips/parameters/notrequired.html
http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
http://www.codeguru.com/forum/showthread.php?t=358333 (see post #2)
http://en.wikipedia.org/wiki/Forward_declaration
C++ has the concept of an "incomplete" class and it is something you need to know.
Using an incomplete class allows you, in many situations, to use a class just knowing it is one, without knowing what is in it.
This enables the class detail to change later without requiring a recompile, thus it is a far weaker dependency in the coupling model.
You need a complete class to:
Have an instance of one.
Derive from it
Call any method on it.
delete a pointer to it.
You only need an incomplete class to:
Hold a pointer or reference to it.
Pass a pointer or reference to a function that takes a pointer or reference. (This can be a function that deletes the pointer, as long as it is fully defined at that point).
I think you only need an incomplete class to declare a function that returns one, and possibly to declare a function that takes one as a parameter, but at the time you define or call the function it needs to be complete, even if you don't use the return value.