Casting between shared_ptr of forward declared class hierarchy - c++

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.

Related

C++ Syntactical anomaly for instantiation of a derived class

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

Multiple Interfaces to a Class in C++

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.

Object A is a member of B and the Object B is a member of A

I have a c++ where in classes A and B each one has a member of the other class. How can I solve this ?
class A {
B memberY;
}
class B {
A memberX;
}
You use pointers and forward declarations.
//A.h
class B; //forward declaration to class B
class A {
B* memeberY;
}
header for class B:
//B.h
class A; //forward declaration to class B
class B {
A* memeberX;
}
You can't do this with object instances, only with pointers, since an instance would require the compiler to know the full definition of the class.
Note that if memory management is assigned to the class, you should free the memory on the destructor. That means you should also override the copy constructor and operator = in your classes.
You can have one of the classes contain an object of the other class, but you have to include the other classes' header in the header. The other one would have to be solved with a forward declaration.
It isn't possible as you would like it. One of those classes has to be a pointer to the other one. You cannot have a recursive relationship of actual objects -- the size of the object would be infinite.
So you probably need something like this:
struct B;
struct A
{
B * myB;
};
struct B
{
A * myA;
};
Now, construction becomes a problem since they both need a reference to each other. That is why I can't provide you with a constructor, since I don't know how you will construct these objects.
You now also have a cleanup problem, since presumably one of these objects owns the other -- they both can't own each other. That excludes the use of unique_ptr. I would have used smart_ptr, but then you still have a memory link unless you have some function to break the circular reference.
But if you'd better indicate why you want to do this perhaps a more appropriate answer can be given.

Problem with declaring Objects in C++

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.

C++ Forward declaration for virtual function

I have a class hierarchy and i am writing a virtual function in it. Say there are three classes
class A { virtual A* test(); }; ( File A.h )
class B : public A { virtual C* test(); }; ( File B.h )
class C : public A {}; ( File C.h )
Now is it possible for me to avoid including C.h in B.h, by doing some kind of forward declaration saying that C is a sub-class of A?
Thanks,
Gokul.
You can tell the compiler only three things, in three different ways, about a class C:
That it exists. You do that by forward-declaring the class.
How it is structured. You do that by declaring the class.
How it behaves. You do that by defining the class' member-functions.
If you want to tell the compiler what the class derives from then you're talking about how the class is structured. You must then show the compiler the class' declaration, there's no other way.
C/C++ distinguish between complete types and incomplete types. If you forward-declare class C like this:
class C;
It will be available as an incomplete type, which means you can declare a pointer to it. However, you can't subclass it until C is fully declared, as C is an incomplete type at this point.
You can use class C inline where you would just use C. What you want is:
class B : public A { virtual class C* test(); };
There's no reason to specify B::test() as returning a C* because a C* will always downcast to an A* and any client making correct use of the interface to A will expect an A*. If clients of B expect only C* they should either call a different function or take responsibility for ensuring the returned A* upcasts to a C* using dynamic_cast.
It's also perfectly fine to forward-declare class C before class A and have A::test() return a C* - subclassing doesn't make any difference when declaring pointers to incomplete types in this case.