behaviour of dynamic_cast up another chain - c++

i was just reading this question here
https://stackoverflow.com/a/332086/2689696
and it tells that dynamic cast
You can use it for more than just casting downwards -- you can cast sideways or even up another chain. The dynamic_cast will seek out the desired object and return it if possible.
so what does this really mean and what are the limitations/ conditions under which this can happen.
and i assume this is what the statement means. And the cast happens and i get a segmentation fault too which is obvious.
#include <iostream>
class base
{
public:
virtual void print () = 0;
};
class childa : public base
{
public:
char c1;
virtual void print ()
{
std::cout << "childa\n";
}
void printout()
{
std::cout << "childa out\n";
}
};
class childb : public base
{
public:
int c2;
virtual void print ()
{
std::cout << "childb\n";
}
void printin()
{
std::cout << "childb in\n";
}
void printout()
{
std::cout << "childb out\n";
}
};
int main()
{
base* b = new childa;
b ->print();
dynamic_cast<childa*>(b)->printout();
dynamic_cast<childb*>(b)->printout(); // cast happens here and the output is printed
dynamic_cast<childa*>(b)->c1 = 'a';
dynamic_cast<childb*>(b)->c2 = 2; // segfault here
}
This is the output i get and a segfault occurs
childa
childa out
childb out
Process returned -1073741819 (0xC0000005) execution time : 5.844 s
Press any key to continue.
EDIT:
Yes it was foolish of me not to check for null value.
but i wanted to know more about the comment from the other question(Up/Down/Sideways)

You're hitting Undefined Behaviour here:
dynamic_cast<childb*>(b)->printout();
The cast actually fails (returns a null pointer). You never check the return value and call a member function through it. That's Undefined Behaviour and anything can happen. In your case, it seems that because the function does not access this in any way, it executes just fine even though invoked through a null pointer. But that's not guaranteed.
As for what a sideways cast (or cast up another chain) is, that needs a more complex inheritance hierarchy to demonstrate:
struct base1
{
virtual ~base1() {}
};
struct base2
{
virtual ~base2() {}
};
struct child1 : base1
{};
struct child2 : base2
{};
struct both : child1, child2
{};
int main()
{
child1 *c1 = new both();
static_cast<base1*>(c1); // ok
static_cast<both*>(c1); // ok
static_cast<child2*>(c1); // compile-time error, unrelated types
dynamic_cast<child2*>(c1); // succeeds, because the object is actually of type `both`, i.e. derived from `child2`; cast sideways
static_cast<base2*>(c1); // compile-time error, unrelated types
dynamic_cast<base2*>(c1); // succeeds, because the object is actually of type `both`, i.e. derived from `base2`; cast up another chain
base1 *b1 = new child1();
static_cast<child1*>(b1); // ok
static_cast<both*>(b1); // compiles, but produces UB, as the object is not of correct type
static_cast<base2*>(b1); // compile-time error, unrelated types
dynamic_cast<base2*>(b1); // fails (returns null pointer), because the object is not actually derived from `base2`.
}

dynamic_cast<T*>(a) returns a not null T* if and only if *a is instance of T; otherwise, it returns NULL.
Invoking a method or attribute from a null pointer produces an undefined behavior.

The usefulness of dynamic_cast is in his answer. With this code
int main()
{
base* b = new childa;
b ->print();
childa* testA = dynamic_cast<childa*>(b);
if (testA)
{
//Here you can be sure that your object is right
testA->printout();
testA->c1 = 'a';
}
else
std::cout << "Error casting b to testA" << std::endl;
childb* testB = dynamic_cast<childb*>(b);
if (testB)
{
//Here you can be sure that your object is right
testB->printout();
testB->c2 = 2;
}
else
std::cout << "Error casting b to testB" << std::endl;
}
you obtain the following output
childa
childa out
Error casting b to testB

Related

How to use inheritance to form a generic callback function pointer?

I am trying to write a function that would take in a generic function pointer as an argument.
Suppose you have a class A and its derivatives like below
class A {
};
class A1: public A {
};
class A2: public A {
};
class A3: public A {
};
I have another function
void registerCallback(std::function<void(A*)> func_ptr) {
}
int main() {
std::function<void(A1*)> fptr= [&](A1*) {
cout << "dummy" <<endl;
};
registerCallback(fptr); /// throws error
}
It tells you, cannot convert std::function<void(A*)> to std::function<void(A1*)>
How can I solve this problem?
How can I solve this problem?
You can use A* instead of A1* in the definition of fptr.
std::function<void(A*)> fptr= [&](A*) {
cout << "dummy" <<endl;
};
It is instructive to understand why your code is erroneous, not just from a syntactic point of view but also from a semantic point of view.
From a syntactic point of view, A1* can be used where A* where is expected -- it is an automatic pointer conversion. However, std::function<void(A1*)> cannot be used where std::function<void(A*)> is expected. There is no automatic conversion.
It's more important to understand the semantic problem if that was not
a syntactic error. Let's say for the sake of this discussion that the language/compiler accepted your code. Let's take the code a bit further. Update your code to the following:
class A {
};
class A1: public A {
public:
int int_var;
};
class A2: public A {
public:
double double_var;
};
class A3: public A {
public:
std::string string_var;
};
static std::function<void(A*)> registered_function_ptr;
void registerCallback(std::function<void(A*)> func_ptr) {
registered_function_ptr = fun_ptr;
}
void callRegisteredFunction(A* a_ptr) {
registered_function_ptr(a_ptr);
}
int main() {
std::function<void(A1*)> fptr= [&](A1* a1_ptr) {
// Expecting a pointer to an A1 object.
// Should be able to use members of A1.
cout << "int_var: " << a1_ptr->int_var << endl;
};
registerCallback(fptr);
A2 a2;
a2.double_var = 20;
// Syntactically correct.
callRegisteredFunction(&a2);
A3 a3;
a3.string_var = "Some string";
// Also syntactically correct.
callRegisteredFunction(&a3);
}
When callRegisteredFunction is executed, it calls the registered function. In this case it is fptr. fptr expects a pointer to an A1 object but we are able to call it indirectly with objects that are different -- they don't have int_var. Instead, they have double_var and string_var. That will definitely lead to undefined behavior. The compiler and the language are preventing you falling into that trap.
Just declare fptr as a callable object with parameter of basic type - std::function<void(A*)>. It will still accept all classes (publicly) derived from A:
int main() {
std::function<void(A*)> fptr= [&](A*) {
std::cout << "dummy" << std::endl;
};
A1 *a = new A1{};
fptr(a); // all good
}

Virtual call from base in virtual inheritance

I'm having a problem making a a virtual call when using virtual inheritance.
Below is sample compilable code that demonstrates a code which works when there is no virtual inheritance used, and also code which will fail on runtime when virtual inheritance is used.
BASE CLASSES
Here are base calsses for both cases:
#include <iostream>
class Base
{
public:
Base() { }
virtual ~Base() { }
// we need to make this bad call a good one!
virtual void bad_call(void* ptr)
{
Base* pThis = static_cast<Base*>(ptr);
pThis->f();
}
protected:
virtual void f() { std::cout << x << std::endl; }
int x = 0;
};
class Midle1 :
virtual public Base
{
public:
Midle1() { }
~Midle1() override { }
};
class Midle2 :
virtual public Base
{
public:
Midle2() { }
~Midle2() override { }
};
CASE 1 GOOD
Here is a case which makes no use of virtual inheritance (just normal inheritance), where both bad_call and good_call virtual functions work:
class GoodDerived :
public Base
{
public:
GoodDerived()
{
}
~GoodDerived() override
{
}
void good_call(void* ptr)
{
GoodDerived* pThis = static_cast<GoodDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
GoodDerived good_derived;
good_derived.good_call(&good_derived); // OK, will print 1
good_derived.bad_call(&good_derived); // OK, will print 2
std::cin.get();
return 0;
}
CASE 2 BAD
And here is a case which will make use of virtual inheritance, the good_call function will succeed, but bad_call one will fail with "access violation reading location"
class BadDerived :
public Midle1,
public Midle2
{
public:
BadDerived() { }
~BadDerived() override { }
void good_call(void* ptr)
{
BadDerived* pThis = static_cast<BadDerived*>(ptr);
pThis->f();
}
void f() override
{
++x;
std::cout << x << std::endl;
}
};
int main()
{
BadDerived bad_derived;
bad_derived.good_call(&bad_derived); // OK, will print 1
bad_derived.bad_call(&bad_derived); // ERROR: causes access violation
std::cin.get();
return 0;
}
QUESTION
This second case is a simple code that demonstrated the issue I'm having right now in my project, and I need assistance on how to solve this, why is virtual inheritance causing troubles?
Why first case works just fine but second one does not?
The basic problem is that you're casting a pointer to void * and then casting it to a different pointer type. That doesn't work in general -- after casting a pointer to void *, the only useful thing you can do with it is cast it back to the EXACT SAME POINTER TYPE. If you want to cast to any other pointer type (reliably) you need to first cast back to the same original type.
I need assistance on how to solve this
Don't use void * here -- void * is a C solution that should never be used in C++. Change your virtual bad_call method to take a Base * as an argument not a void *. Then everything 'just works' and you don't need any of the static_casts at all. If you need to override bad_call in your Dervied class, it also needs to take a Base * argument, so you'll need to use dynamic_cast<Derived *>(ptr) there to get back the original Derived *, but that's not a big deal -- that's precisely what dynamic_cast exists for.
Make your call:
bad_derived.bad_call(static_cast<Base*>(&bad_derived));
You want to point to the Base part of the object but when using virtual inheritance there is no guarantee about where that will be located.
Let's decompose this, step by step.
&bad_derived: A pointer to BadDerived with pointer value pointing to an object with type BadDervived.
bad_derived.bad_call(&bad_derived): Implicitly converts &bad_derived to a pointer to void* with pointer value pointing to an object with type BadDervived.
Base* pThis = static_cast<Base*>(ptr);: Cast from a void* to Base*. Note that ptr has pointer value pointing to an object with type BadDervived, but BadDerived is not pointer-interconvertable with Base, thus pThis has type Base* but has pointer value pointing to an object with type BadDervived.
pThis->f();: Access the value of a BadDerived object using a glvalue (here a dereferenced pointer) of type Base, violates the strict-aliasing-rule. Undefined Behaviour.
I want to share a solution that makes this design possible (with the help of other answers and comments).
All the code remains same except adding a templated static mehtod to base class which will deduce void to correct type:
Here is modified Base class with helper template static function:
added a comment about CALLBACK also.
class Base
{
public:
Base() { }
virtual ~Base() { }
// this is example CALLBACK from Window API but templated
// The callback is registered with Windows in RegisterClassEx btw.
template<typename DERIVED_CLASS>
static void make_call(void* ptr)
{
DERIVED_CLASS* pThis = static_cast<DERIVED_CLASS*>(ptr);
pThis->bad_call(static_cast<Base*>(pThis));
}
// we need to make this bad call a good one!
virtual void bad_call(void* ptr)
{
Base* pThis = static_cast<Base*>(ptr);
pThis->f();
}
protected:
virtual void f() { std::cout << x << std::endl; }
int x = 0;
};
And here is how we invoke bad_call problematic function:
int main()
{
BadDerived bad_derived;
bad_derived.good_call(&bad_derived); // OK, will print 1
// HACA!!!
bad_derived.make_call<BadDerived>(&bad_derived); // OK will print 2
std::cin.get();
return 0;
}
This why I like C++ so much, everything is possible...

Program should fail/crash while dynamic_cast is working

In my opinion following program should be crashed but its not only working but showing the right result("derv is called").
#include <iostream>
using namespace std;
class base
{
public:
virtual ~base(){}
};
class derv: public base
{
public:
void f() { cout << "derv is called" <<endl;}
};
int main() {
base* p = new base();
derv *d1 = dynamic_cast<derv*>(p);
// Since p point to base , so d1 should return nullptr
//calling any function using d1, should fail/crash
//but why the following line is working ??
d1->f();
}
Sorry I forgot to add few lines in my previous post: If I add a single data member and try to access it, gives me segmentation fault, which I think is the correct behavior. My Question is that why accessing data member changes the behavior ? When variable is not get accessed , calling "f()" function is successful while the same function "f()" gives segmentation fault when accessing with the data member? Is it the undefined behavior?
class derv: public base
{
public:
int x = 0 ; // Added new member, c++11
void f() { cout << "derv is called " << x << endl;} //access it here
};
It is undefined behavior in your program you dereferencing d1 which is a NULL pointer:
base* p = new base();
derv *d1 = nullptr;
d1 = dynamic_cast<derv*>(p);
if(nullptr == d1) // condition succeeds which means d1 is nullptr
cout << "nullptr" << endl;
A safe programming is the task of the programmer not the compiler's so a good program checks before uses:
// avoiding error prones and UBs
if(nullptr != d1)
d1->f();
f is not a virtual function. The program does not have to look for the virtual function table when trying to call f, so the method is called anyway.
If you try to check the pointer value of this inside of f, it will be nullptr.

Safe to use static casting for performance in a unique virtual int type() for each instance?

I have a dense hierarchy of polymorphic objects, each of which comes with a mandatory virtual int type() = 0 method, which is manually written for every object.
The "safe" processing of the tree using dynamic_cast has a significant overhead, and as I already have a virtual method which will return a unique integer for each different type, I think it is safe to use an unsafe static cast. But I might be overlooking something, for example in cases of multiple inheritance or something else which may cause a misalignment which may cause the static cast to "crash"?
The hierarchy is traversed on base class level by different contexts, each of which has a custom way of interpreting the data, so for each object there is switch (type) and "do according to type" where the casting takes place.
The type() virtual is declared in the "utmost-base-class", which is always first in the inheritance.
According to the standard 5.2.9/2 the static cast you intend to do is safe, under the condition that the base class in not a virtual base class, nor a base of a virtual base class.
Here the example provided in the standard:
struct B { };
struct D : public B { };
D d;
B &br = d;
static_cast<D&>(br); // produces lvalue to the original d object
// Note that this works because B is not a virtual base class
So unless you use multiple inheritance with virtual bases, it's ok.
But be carefull if you have somethink like:
struct B { };
struct D1 : public virtual B { };
struct D2 : public virtual B {};
struct E : D1, D2 {};
E e;
B *pb=&e; //
static_cast<E*>(pb); // ouch !!! This would not safe
D1 *pd1 = &e;
static_cast<E*>(pd1); // but this would be ok
You can replace the use of dynamic_cast with static_cast in your code as long as you make sure that conversion is actually doing the right thing. dynamic_cast involves some run-time overhead which is missing from static_cast.
However, I am not sure if there could be some implication of replacement in case of multiple/virtual base classes. I had encountered a scenario where I stored addresses returned by operator new and then on later checking it showed that address is not present.
//Get the address from new
void* operator new(size_t size);
//Store this address in list.
std::list<void*> rawAddresses;
//Function to check if address is present
isAddressPresent(void* address) <<< This vomitted error when I passed object of
<<< class which has virtual base.
Using static_cast in this way should be fine -- as long as you can guarantee that you're casting to the correct type. I would highly recommend a simple unit test which can verify that you don't have any type() collisions (eg, a copy-paste error could cause SubclassB to have the same type() id as SubclassA) -- just add all types to a map and check for collisions. Further, you can safe-ishly create helper functions which guarantee the correct type (depending on your usage pattern). Here's an example.
// g++ test.cpp --std=c++11
#include <iostream>
#include <cassert>
#include <stdexcept>
class Base {
public:
virtual int type() = 0;
};
class SubClassA : public Base {
public:
virtual int type() override { return 1; }
};
class SubClassB : public Base {
public:
virtual int type() override { return 2; }
};
class BaseConversion {
public:
BaseConversion(Base *ptr) : _ptr(ptr) {}
Base *_ptr;
template<typename T>
operator T() const {
throw std::runtime_error("invalid Base * type()");
}
};
template<>
BaseConversion::operator SubClassA*() const {
if ( _ptr->type() != 1 ) {
throw std::runtime_error("type() not SubClassA");
}
return static_cast<SubClassA*>(_ptr);
}
template<>
BaseConversion::operator SubClassB*() const {
if ( _ptr->type() != 2 ) {
throw std::runtime_error("type() not SubClassB");
}
return static_cast<SubClassB*>(_ptr);
}
int main(int argc, char **argv) {
Base *ptr = new SubClassA();
try {
SubClassA *a = BaseConversion(ptr);
} catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}
try {
SubClassB *b = BaseConversion(ptr);
} catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}
return 0;
}
It does mean you'd need to specialize a template for each subclass of Base. However, this also means you can write a unit test for each which exercises the conversions and helps ensure that you always check for the correct type() id and convert to the correct subclass (by having to only write SubClassA once in the pointer declaration/allocation instead of also in the static_cast).
This won't help you (performance wise) if you do something like this:
switch (ptr->type()) {
case 1:
SubClassA *a = BaseConversion(ptr);
/* do stuff with a */
break;
case 2:
SubClassB *b = BaseConversion(ptr);
/* do stuff with b */
break;
}
...since you'd effectively be checking type() twice. However, as long as type() just returns an integer and doesn't have to do calculations to figure out what type it is, the performance shouldn't be terrible if you do (there are far worse things you could do). Note that, because of static_cast, this does effectively remove any constness of the given pointer! There are probably ways to resolve that but I'll leave that as a further exercise for you since I'm lazy.

Weird casting behaviour

could somebody explain the output of the code.
#include <iostream>
using namespace std;
class First {
public:
int a;
First() {};
First(int a) {
this->a = a;
}
int getA() {
return a;
}
virtual int getB() {
cout << "getB() from super class..." << endl;
return 0;
}
};
class Second : public First {
public:
int b;
Second(int b) {
this->b = b;
}
int getB() {
cout << "getB() from child class..." << endl;
return b;
}
};
int main() {
First* t = new Second(2);
First* cTest = dynamic_cast<First*>(t);
cout << cTest->getB() << endl;
}
I expected the method of the super class would be called because of the casting to First.
thanks in advance
regards sebastian
The function getB() is virtual in the base class, so you get the derived implementation no matter whether you have a pointer-to-base or pointer-to-derived.
(That's the whole purpose of polymorphism.)
A dynamic cast up the hierarchy doesn't change the fundamental fact that you're still pointing at a B. In particular, it doesn't change the vtable used to find the implementation of getB() that will be used.
Typically, you only need dynamic_cast() to go down an inheritance hierarchy, not up.
There only exists one object, and that is of type Second.
To get the behaviour you are looking for, you are going to have to create a copy and slice it:
First cTest = static_cast<First>(*t);
cout << cTest.getB() << endl;
You aren't changing anything with your cast. You are casting a First* to a First*, which is simply an assignment. Since t is a Second with = new Second(2), you have overridden the virtual table with the child's entries, so it will call the child's methods rather than the parents.
cTest is simply a pointer-to-First which points to the exact same object that t does, because cTest and t contain the same memory address, at which exists a Second object, which is why the Second's method is called.