What is a transverse pointer cast? - c++

I encountered this in Horstmann's Core Java, Volume 1:
C++ has multiple inheritance and all the compications that come with it, such as virtual base classes, dominance rules, and transverse pointer casts...
Core Java Volume I: Fundamentals [Horstmann, Cay S. 2016 Prentice Hall 10th ed. §6.1.3 p. 297]
Now, I am familiar with the other two, but what is a transverse pointer cast? Is it the term for casting a pointer to a base class as a derived class?

I've never seen the term before, but I reckon this is another name for a cross-cast, when you need to cast "across" (rather than "up" or "down") an inheritance graph. Take the following situation:
// V-shaped inheritance graph
// [ Base1 ] [ Base2 ]
// \ /
// \ /
// [ Derived ]
struct Base1 { };
struct Base2 { };
struct Derived : Base1, Base2 { };
// ...
// Take an object of derived type
Derived d;
// Upwards conversion, we get its Base1 subobject
Base1 *b1 = &d;
Now suppose we only have b1, of static type Base1 and dynamic type Derived, and we want to reach the Base2 subobject, that is, convert across the V's branches.
The issue is, we lost the information that *b1 is actually a subobject of a Derived. It could be a subobject of any other class, or an object on its own. We have to use one of two tools:
// If we know by other means that b1 is for sure a Derived,
// walk the graph explicitly through Derived
Base2 *b2 = /* implicit upwards conversion */ static_cast<Derived*>(b1);
// If Base1 is polymorphic (i.e. has at least one virtual function)
// Let RTTI do the job and check for errors. Slower but safer.
Base2 *b2 = dynamic_cast<Base2 *>(b1);

Related

C++ V-shape casting: vector<Base1*> to vector<Base2*>

I'm having real trouble to figure out this casting problem. Starting with 3 classes:
#include <vector>
// Pure virtual class
class Base1{
public:
virtual ~Base1();
virtual void do_sth()=0;
}
class Base2{
public:
int prop=3;
~Base2();
}
class Derived: public Base1, Base2{
~Derived();
void do_sth(){print("Hi");};
}
How can I perform the following conversion?
std::vector<Base1*> vec1
vec1.reserve(10);
for( int i = 0; i < 10; ++i )
vec1.push_back(new Derived());
// To this type...?
std::vector<Base2*> vec2 = ?????;
Some remarks:
I'd use dynamic_cast to perform safe casting from Base1 to Derived.
Ideally, no object copies are made in the process!.
My best bet so far is to call vec2.data() to obtain a Base1* pointer, then dynamic_cast to Derived, then static cast to Base2, but I don't know how to transfer memory ownership nor how to pass vector size.
The comments to the question have gotten rather muddled, so I'll post this partial answer here, rather than trying to straighten out the comments.
Base1 has a virtual function. Good start.
Derived is derived from Base1.
Derived is also derived from Base2.
If you have an object of type Derived you can create a pointer to Base1 that points at the derived object:
Derived d;
Base1* b1 = &d;
Now that you have a pointer to a polymorphic base class, you can use dynamic_cast to perform a cross-cast:
Base2* b2 = dynamic_cast<Base2*>(b1);
The compiler knows how to do that, and the result should be the same pointer value as you'd have gotten if you did it directly:
Base2* b2x = &d;
assert(b2x == b2);
Note, too, that since the code traffics in vectors of pointers, it seems that the Derived objects are being created with new Derived. If that's the case, and eventually the code deletes the Derived object through a pointer to one of the base types, then the base type must have a virtual destructor.
There are no Derived objects in vec1 nor vec2, so you can't get pointers to other base subobjects of a Derived from an element of either.
If pass a Derived to vec1.push_back, it will copy-construct a Base1 from the Base1 subobject of the Derived. This is called object slicing.
If you have a vector of pointers (raw or smart) to Base1 in vec1, then those could point to the Base1 base subobject of a Derived, at which point you can dynamic_cast<Base2*> them, which will in general give you a different pointer value.

Why don't the two pointer values be the same?

Quoting Effective C++, Scott Meyer, 3rd Edition , Item 27
class Base { ... };
class Derived: public Base { ... };
Derived d;
Base *pb = &d; // implicitly convert Derived* ⇒ Base*
Here we’re just creating a base class pointer to a derived class
object,
but sometimes, the two pointer values will not be the same. When that’s the case, an offset is applied at runtime to the Derived*
pointer to get the correct Base* pointer value.
Why are the two pointer values not the same? If it is because how the child and parent objects are laid out in the memory, then how does downcast work later?
This always happen when using multiple inheritance.
class Base1 { int a; };
class Base2 { double b };
class Derived : public Base1, public Base2 { ... };
Derived d;
Base1* pb1 = &d;
Base2* pb2 = &d;
Now &d cannot possibly be equal to both pb1 and pb2, because otherwise pb1 would equal pb2, which is not possible, because two different non-empty objects of unrelated types must occupy different regions of memory. So in at least one case a non-zero offset must be applied.
In most implementations with single inheritance the offset is zero, but the standard does not mandate that.
Indeed, a typical implementation would simply lay out the base object at the beginning of the derived object:
++-----++
||Base ||
|+-----+|
|Derived|
+-------+
But when there are more than one base, only one can go at the beginning:
++-----++
||Base1||
|+-----+|
||Base2||
|+-----+|
|Derived|
+-------+
The downcast works because the offset is fixed and known at compile time, so there's no problem to apply it when either upcasting or downcasting.
An exception to this is virtual inheritance. For a virtual base the offset is not known at compile time. Typically, the derived object contains an internal hidden pointer to its virtual base, so the upcast can work. But the base doesn't know where its derived object is, so the downcast cannot work, and is not allowed by the language.
When you have a single inheritance tree that is polymorphic, compilers require each object to begin with a VMT (virtual method table). If base class is polymorphic, the pointer values would match. But ff your base class is non-polymorphic and your derived class is polymorphic, the base class does not introduce the VMT, it is introduced by the very first polymorphic class down the tree. The VMT would be inserted before the base. Now the pointer values will not match.

If derived class contains only base class element ,then downcast is possible using dynamic_cast in c++

class Base { virtual void dummy() {} };
class Derived: public Base { // no new elements added }
I like to know that
base *bptr;
derived *dptr;
bptr=new base;
dptr=dynamic_cast<derived*>(bptr); // this is not working ,dptr is NULL
dynamic_cast can also downcast (convert from pointer-to-base to pointer-to-derived) polymorphic classes (those with virtual members) if -and only if- the pointed object is a valid complete object of the target type"
here the pointed object is base object and is same as target object.
so here "complete" means some other meaning
thanks
dynamic_cast will only succeed if the dynamic type of the object matches the type you're casting to. Here
bptr=new base;
points to a base, not a derived, so dynamic_cast<derived*> will fail; there is no derived object it could point to. derived is a different type to base, even if it doesn't declare any members beyond those in the base class.
Try
bptr=new derived;
and the cast should succeed.

Base class pointer to Derived class pointer using the already allocated memory

Take two classes that both can only be created by new. One class is the base and the other is a derivative. The derived class only adds methods.
class Base
{};
class Derived : public Base
{};
Base * b = new Base{}
Derived * d = covert( b );
// - or -
Base * b = new Base{};
convert( b ); // converts Base to Derived
Derived * d = dynamic_cast<Derived *>(b);
What I want to do is take the Base class data that has been allocated and extend/wrap with the derivative via some method or function, convert.
Update:
Building for embedded systems memory is scarce, so I am doing everything I can to reduce that amount of memory allocation. I was just wondering if there was a way to just sort of extend the base class already allocated memory and wrap it with the derivative.
More Updates:
Although the embedded system is ARM and I am currently using LLVM compiler this might not be true in the future. So a standard compliant way is preferred.
If I understand correctly your question one possible solution is to use aggregation instead of inheritance.
class Base
{/*has only the data*/}
class Derived
{
Base &base;
Derived(Base &b) : base(b) {}
//now methods from derived will use the data members from instance passed in constructor
//if is possible the Derived needs to be a friend class of Base in case there are no getter for all members
}
Instead of reference we can use a smart pointer if necessary.
This way you avoid the cast by constructing a new Derived object which uses the data from the a Base object.
Promoting classes is not possible in C++. What you might want to do is - like you said - wrap Base in Derived:
class BaseInterface { ... };
class DerivedInterface: public BaseInterface { ... };
class Base: public BaseInterface { ... };
class Derived: public DerivedInterface {
private:
Base* base;
public:
Derived(Base* useBase): base(useBase) {}
~Derived() { delete base; }
// implement using base
};
And use it like that:
Base* object = new Base(...);
// use object with base functionality
object = new Derived(object);
// use object with derived functionality
delete object; // free both base and derived memory
The derived class only adds methods.
Then there is no point to that class. At all.
You can use deriving to:
override virtual methods (and thus customize behaviors) => Good
extend the data of the base class => Bad, code reuse should use composition, still it works
In your particular case ? It's just useless. It does not bring anything to the table. If you wish to add new functionalities to your base class, then implement free functions. And as a bonus, getting rid of the derived class, you'll also get rid of the need to cast.
A potential option comes about thanks to C++11
class Base
{
pubilc:
Data data;
Base( Base && base ) : data( std::move( base.data ) ) {}
};
class Derived : public Base
{
pubilc:
static Derived * convert( Base *& base )
{
Derived * d = new Derived{ std::move( *base ) };
delete base;
base = d;
return d;
}
};
Although it is not what I hoped for memory-wise it is only a small hit, as far as I am aware. By using the move construct, the only overhead is the creation of a new Derived object before deleting the old Base object.
There should be a check before anything is done, but this will do for now.
You could add a helper class which is a friend of the base class, and add extra functions to that, e.g.
class Base
{
friend class BaseHelper;
// ....
};
class BaseHelper
{
public:
// all functions can access data into Base objects:
void f(const Base& b) const; // can only read data in b, not change it
void g(Base& b); // can change data in b
}
Derived *d =static_cast<Derived *>(b); //? :-/
Here is one explanation
Another explanation
Much more detailed explanation of what's happening under the hood
UPDATE:
Stack Overflow - Downcasting using the static_cast in c++
Downcasting in C++ using static_cast
SPECIFICATION:
An rvalue of type “pointer to cv1 B”, where B is a class type, can be
converted to an rvalue of type “pointer to cv2 D”, where D is a class
derived (clause 10) from B, if a valid standard conversion from
“pointer to D” to “pointer to B” exists (4.10), cv2 is the same
cvqualification as, or greater cvqualification than, cv1, and B is not
a virtual base class of D. The null pointer value (4.10) is converted
to the null pointer value of the destination type. If the rvalue of
type “pointer to cv1 B” points to a B that is actually a subobject of
an object of type D, the resulting pointer points to the enclosing
object of type D. Otherwise, the result of the cast is undefined.
FOR LLVM ONLY:
http://llvm.org/docs/HowToSetUpLLVMStyleRTTI.html - ALLOWS DOWNCASTING(is not undefined behavior, since it doesn't use C++ RTTI).
There is no standard-compliant way of downcasting:
class Parent{
public: void gotoWork(){ cout << doWork(); }
};
class Child: public Parent{
public: void gotoSchool(){ cout << attendClasses();}
};
Parent *p = new Parent();
Child *ch = static_cast<Child*> p;
//now child has to go work? :-(
EDIT
Apart from all other ways, why not put two objects? one of type "Base"
and another of type "Derived" into a UNION?
PS: Its language-specification conformant.
Looking through the many answers that I have, the common consensus is that I should do what I said and actually wrap my Base class within the Derived class. The reason I was not doing this is I would lose a particular behaviour you get with inheritance. This behaviour is setting a pointer of the Derived class to a pointer of type Base, which will happen after I did some sort of conversion that will make the Base class transform into the Derived class.
A did stumble on a solution of my own - although apparently it may not compile - and have had many other good ideas as well. In the end, I was a bit slow to realise that because, for my case, my Derived class does not override any virtual methods there was no benefit of using inheritance. The best way is indeed to to use composition.
class Base
{
// some nice implementation
};
class Derived
{
public:
Derived( Base && base )
{
this->_base = base;
}
Base & base()
{
return _base;
}
private:
Base _base;
};

A Base Class pointer can point to a derived class object. Why is the vice-versa not true?

A Base Class pointer can point to a derived class object. Why is the vice-versa not true without casting?
Logically a base class would not have enough information of the derived class but a derived class should have the information of the base class as well.
I am missing some basics here.
If I tell you I have a dog, you can safely assume that I have a pet.
If I tell you I have a pet, you don't know if that animal is a dog, it could be a cat or maybe even a giraffe. Without knowing some extra information you can't safely assume I have a dog.
similarly a derived object is a base class object (as it's a sub class), so it can be pointed to by a base class pointer. However, a base class object is not a derived class object so it can't be assigned to a derived class pointer.
(The creaking you will now hear is the analogy stretching)
Suppose you now want to buy me a gift for my pet.
In the first scenario you know it is a dog, you can buy me a leash, everyone is happy.
In the second scenario I haven't told you what my pet is so if you are going to buy me a gift anyway you need to know information I haven't told you (or just guess), you buy me a leash, if it turns out I really did have a dog everyone is happy.
However if I actually had a cat then we now know you made a bad assumption (cast) and have an unhappy cat on a leash (runtime error).
We have two objects.
class A {
int a;
};
class B : A {
int b;
};
Allocate an instance of B. We can interface with that as either an A* or a B*.
Allocate an instance of A. If we were to cast it to a B*, should there be space allocated for the member b?
Uh, because the base class is not a derived class.
When you have a valid pointer to a type, then you are saying that the object pointed to will have certain data in certain locations so that we can find it. If you have a pointer to a derived object, then you are guaranteeing that the pointed-to object contains all of Derived's data members- but when you point to a Base, then it infact doesn't have that and Bad Things Happen™.
However, Derived is guaranteed to have all of the Base data members in the same locations. That's why a pointer to Base can actually point to Derived.
Because a derived class includes everything that is in the base class. But a base class does not include everything that is in the derived class.
Type casting a base class to a derived class is not recommended: What happens if you try to access members that are not part of the base class?
This is valid, because a tiger is an animal:
Animal * pAnimal = new Tiger();
This is not valid, because it is not true that the object is a poison dart frog.
PoisonDartFrog * pPoisonDartFrog = new GenericFrog();
The short answer
class A{
public:
method1();
};
class B: public A{
public:
method2();
};
int main(){
// Case 1
A* ptr_base = new B();
// Here I can call all the methods in A by ptr_base even though it is assigned B ...
// ... because B is derived from A and has all the information about methods of A
// Case 2
B* ptr_derived = new A(); // this will cause error
// Now here ptr_derived is assigned information of A ...
// ... So with this information can I call (*ptr_derived).method2(); ?...
// ... the answer is No because A does not have information of method2() ...;
// ... thus this declaration loses its meaning and hence error.
return 0;
}
Because C++ is a statically typed language, and allowing implicit Base-to-Derived conversions would break the type system. Bjarne Stroustrup did not want any "message not understood" runtime errors.
class Base
{
public:
int a;
}
class Derived : public Base
{
public:
float b;
}
Base * pBase = new Base();
pBase->a = 7; // setting the value of a in the base
// make a pDerived that points to the SAME DATA as pBase
Derived * pDerived = pBase;
pDerived->a = 5; // this would be okay, base has a public member 'a'
pDerived->b = 0.2f; // error pBase has no data member b and pDerived
// points to the SAME DATA as pBase
This is because, "the type of a pointer is the type of object the pointer points to". So,
If we have base type pointer (*B):
then we expect a base type object (and would like to access its functionalities) at the address pointed by B, and if we get a derived type object at that address then also we are able to access the required functionalities. This is because derived type is-a base type.
If we have derived type pointer (*D):
then we expect a derived type object at the address pointed by D and if we get base type object there then we will not be able to access derived class info from the base type object since base type is-not-a derived type.
Actions speak more than words.
Child too can have Parent Class object.
if you understand pointers well, limitations are off to you
In below code have printed both values by child class pointer ( which was having Parent class object).
Also proved that by printing their address.
Any suggestions are welcome!
#include<iostream>
using namespace std;
class Baap{
public:
int a;
void hoo(){ cout<<"hoo\n"; cout<<a;}
};
class Beta:public Baap{
public:
int a;
int b;
void hee(){ cout<<"hee\n"; }
};
int main(){
Baap baap;
baap.a=1;
Beta *beta=(Beta*)&baap;
baap.a=3;
beta->hee();
beta->hoo();
cout<<"\n beta = "<<beta<<"\n&baap = "<<&baap;
return 0;
}
//output
hee
hoo
3
beta = 0x7ffd11dd3834
&baap = 0x7ffd11dd3834
Because a base class pointer can point to an instance of the base class or any derived type. A derived pointer can only point to that derived type or any subclass of it.
struct Base {};
struct Derived : Base {};
struct Derived2 : Base {};
Base* p = new Derived(); //Fine, Derived inherits from Base
Derived* d = new Base(); //Not fine, Base is not an instance of nor derived from Derived.
Derived* d2 = new Derived2(); // Also not fine, Derived2 derives from Base, but is not related to Derived.
As far as the why goes: In general the base pointer is more general than the derived pointer. As such it knows less about the inherited type. A derived pointer cannot be assigned a pointer to a base type without casting simply because it cannot tell if the base pointer is of the Derived type or one of its children.
If assign an address from a base class pointer into a derived class pointer, you can potentially assign a base class object to a derived class pointer. You run the risk of accessing derived class members when you don't have a derived class. Whereas derived class methods would work on a base class, they would only do so if the method didn't access derived class member data.
That's a huge risk.
So we force you to cast so that you have to acknowledge the disclaimer that says (you may make a stupid mistake, please be careful).
In general , a pointer of one type cannot point to an object of a different type. However, there is an important exception to this rule that relates only to derived classes.
In this situation a pointer of type BASE* may point to an object of type Derived, i.e a base class pointer can point to a derived class object but vice versa is not true as the base object is not it's sub class object.