using dynamic_cast to point to other derived class object - c++

I have the following scenario. There are two Base classes: Base1, Base2 and two derived classes: Derived, sysCommandExecutor which are derived as follows:
#include <iostream>
using namespace std;
class Base1 { virtual void dummy() {} };
class Base2 { virtual void dumy() {} };
class Derived: virtual public Base1, public Base2
{ int a; };
class sysCommandExecutor : public Base2
{
public:
int b;
Base1 *ptr;
void func(void);
};
void sysCommandExecutor::func(void)
{
Derived *d;
d = dynamic_cast<Derived *>(ptr);
if (d == NULL)
std::cout << "This is NULL" << std::endl;
else
{
// Call a function of Derived class
}
}
int main () {
try {
sysCommandExecutor * sys = new sysCommandExecutor;
sys->func();
return 0;
}
}
I want to call this function of "Derived" class inside func but the dynamic_cast fails.
I cannot create the function in the sysCommandExecutor class as that is someone else's code.
How to make the ptr pointer in sysCommandExecutor class to point to Derived class object??
Thanks in advance

You are referencing an uninitialized pointer ptr
if i change main to:
int main () {
sysCommandExecutor * sys = new sysCommandExecutor;
sys->ptr=new Derived;
sys->func();
delete dynamic_cast<Derived *>(sys->ptr);
delete sys;
return 0;
}
it works
you are missing a virtual dtor as well

Related

The best way to implement cloneable c++ classes?

I have seen solutions (including in this site) to the problem of having to implement a clone method in a class, so it returns a heap-allocated clone of itself even if we only have the Baseclass.
The problem come up when you have to implement in a lot of classes the same method again and again, and I remember a way of doing this when you only have to inherit from a template class (name it Cloneable) so it implements it, but the way i'm trying to do it doesn't work:
template<typename T, typename B> class Cloneable{
public:
B* clone(){return new T(*this);}
};
class Bottom {
public:
virtual void sayhi() = 0;
virtual Bottom* clone() = 0;
};
class Middle: public Cloneable<Middle, Bottom>, public Bottom {
public:
void sayhi() override {cout << "Hi from the Middle" << endl;}
};
//class Top: public Middle ...?
int main() {
Bottom* b1 = new Middle();
b1->sayhi();
delete b1;
}
I remember that the person that showed this to me actually did it with just one argument in Cloneable, but anyways, i would thank any way that you can imagine of doing this.
You could use the Curious Recurring Template Pattern where a derived class actually derives from an instanciation of it base class depending on itself. Demo:
#include <iostream>
template<typename T>
class Clonable {
public:
T* clone() {
return new T { * static_cast<T *>(this)};
}
};
template<class T>
class Base : public Clonable<T> {
public:
int x = 2;
virtual ~Base() {}
};
class Derived : public Base<Derived> {
public:
int y = 3;
};
int main() {
Base<Derived> *d = new Derived;
static_cast<Derived *>(d)->y = 6;
Derived *c = d.clone(); // we are even cloning from a Base *!
std::cout << c->x << ' ' << c->y << '\n';
delete c;
delete d;
}
It compiles with no warning and correctly outputs 2 6, proving that no slicing occurred.
Your Cloneable is missing a cast. this is a Cloneable *, it needs to be cast to T * to be passed to the copy constructor.
template<typename T, typename B> class Cloneable : public B
{
public:
B* clone() override { return new T(*static_cast<T*>(this)); }
};
class Base
{
public:
virtual Base* clone() = 0;
};
class Derived : public Cloneable<Derived, Base>
{
};
See it live
This doesn't stop someone from further subclassing Derived, and forgetting to reimplement clone for that grandchild class.
class Oops : public Derived {};
int main() {
Oops o;
Base * pb = o.clone();
assert(typeid(*pb) != typeid(o));
}

Call derived class method from base class instance without casting

There is another way to call derived class method from a base pointer object without casting?
class Base
{
};
class Derived : public Base
{
public:
void set() {printf("bbbbbbbbbbbb"); }
};
int main()
{
Base* pbBase;
pbBase = new Derived();
//pbBase->set(); // Compilation error.
(Derived*)pbBase->set(); // Working.
}
You can add virtual methods in Base that you override in Derived.
Note that you should make the destructor virtual too or else the derived class' destructor would not get called when you delete the object through a base class pointer.
#include <iostream>
class Base
{
public:
virtual ~Base() = default;
virtual void set() = 0; // = 0 makes it pure virtual
};
class Derived : public Base
{
public:
void set() override { std::cout << "bbbbbbbbbbbb\n"; }
};
int main()
{
Base* pbBase;
pbBase = new Derived();
pbBase->set();
delete pbBase;
}

Dynamic_cast not showing the right object type

I spent a lot of time trying to figure out why my code displays "Derived3" after I run it and I cannot understand it at all. From what I have read here on many posts, dynamic_cast should somehow say whether a pointer (in this case b) is (in this case) Derived2 or not. However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class. I am just wondering why the program displays "Derived 3" instead of not showing anything, since b pointer is clearly not pointing to a Derived2 object.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: virtual public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: virtual public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Derived,public Derived2{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
However, after editing the code a little bit, it works as it should be.
#include <iostream>
using namespace std;
class Base
{
int b;
public:
virtual void display()
{
cout<<"Base"<<endl;
}
};
class Derived: public Base{
public:
void display()
{
cout<<"Derived"<<endl;
}
};
class Derived2: public Base{
public:
void display()
{
cout<<"Derived 2"<<endl;
}
};
class Derived3:public Base{
public:
void display()
{
cout<<"Derived 3"<<endl;
}
};
int main()
{
Base *b = new Derived3();
Derived2 *aux = dynamic_cast<Derived2*>(b);
if(aux)
{
aux->display();
}
return 0;
}
Inheritance is a "Is-a" relationship.
Every Derived is both a Derived and a Base. By that pattern, every Derived3 is a Derived3, a Derived2, a Derived and a Base at the same time.
It would thus not make sense for that cast to fail.
The output is then finally the result of a normal virtual function call on a Derived2*. This is no different than in the most trivial example of inheritance, like in this snippet:
#include <iostream>
struct A {
virtual void fun() const {
std::cout << 'A';
}
};
struct B : A {
void fun() const {
std::cout << 'B';
}
};
int main () {
const A &a = B();
a.fun(); // prints 'B'
}
If you have a pointer or reference to some base class, a virtual function call will resolve to the actual type of the object it is called on. In your case, that's a Derived2* pointing to a child-class of type Derived3, so the function is looked up in the latter.
Keep in mind that the dynamic_cast only changes the type of the pointer, not the type of the object it points to!
However, it passed the condition and when it should print out the display() function from Derived2 class, it strangely displayes the one from the Derived3 class.
That's because of dynamic dispatch. Remember that display() is declared to be a virtual member function. It continues to be a virtual member function for all the derived classes.
Even though you cast the pointer from Base* to Derived*, the underlying object is still a Derived3. Hence, the dynamic dispatch mechanism calls Derived3::display().
Derived3::display() will also be called if you use:
Base *b = new Derived3();
b->display();

Do I need to override my virtual function using an inherited object (vs. base object)?

Say I have a base class Base, and two derived classes Derived: public Base and Derived2: public Base.
I have a purely virtual function
virtual int CompareByInsertKey( Base* item_in_list ) = 0;
In class Base. So it's a function that takes a pointer to a Base class.
I want my class Derived to overwrite this virtual function but I want it to take a pointer to a Derived class as an argument.
I also want my class Derived2 to overwrite this function but I want to to take a pointer to the Derived2 class as an argument.
Does it do this automatically if I keep the argument as Base* item_in_list because Derived and Derived2 are part Base classes?
If not, how do I do this?
Thanks, if you need me to post more information, please comment.
it takes pointers to the derived classes automatically because Derived * is implicitly convertible to Base *. You will have to implement it using Base in the function argument in order to override the function though.
virtual int CompareByInsertKey( Base* item_in_list ) override
{
Derived *ptr = dynamic_cast<Derived *>(item_in_list);
// ...
}
The compiler cannot do what are hoping to do.
struct Base
{
virtual int CompareByInsertKey( Base* item ) = 0;
};
struct Derived : Base
{
virtual int CompareByInsertKey( Base* item )
{
return 1;
}
};
struct Derived2 : Base
{
virtual int CompareByInsertKey( Base* item )
{
return 2;
}
};
int main()
{
Base* d1 = new Derived;
Base* d2 = new Derived2;
d1->CompareByInsertKey(d2); // This is a valid call
// but the argument is not of type Derived*
}
In order for the function signatures to match you have to use Base* in CompareByInsertKey. Unfortunately, that means you could pass a Derived as the parameter on a Derived2. Maybe templates would work better for your app.
Try running the following example.
#include "stdafx.h"
using namespace std;
class Base {
public:
string name;
Base(string n) : name(n) {}
virtual int CompareByInsertKey(Base* item_in_list) = 0;
virtual string Name() { return name; }
};
class Derived : public Base
{
public:
Derived() : Base("derived") {}
int CompareByInsertKey(Base *item_in_list)
{
cout << "In Derived, parameter is " << item_in_list->Name() << endl;
return 0;
}
};
class Derived2 : public Base
{
public:
Derived2() : Base("derived2") {}
int CompareByInsertKey(Base *item_in_list)
{
cout << "In Derived2, parameter is " << item_in_list->Name() << endl;
return 0;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Base * d2 = new Derived2();
Base *d = new Derived();
d2->CompareByInsertKey(d);
return 0;
}
KC
You can do this via a more complicated structure and knowledge about the types
class Base
{
public:
int publicComparator(Base* instance)
{
// you can use either typeid() or your on enum that you put in the
// hierarchy
if (typeid(this) == typeidf(instance))
{
return privateComparator(instance);
}
return ErrorCode;
}
private:
virtual privateComparator(Base *instance) = 0;
}
class Dervied : public Base {
private:
privateComparator(Base* instance) override {
// The assumption is privateComparator is only called when this cast
// can sucessfully be completed
Derived* derivedInstance = static_cast<Derived*>(instance);
// Do functionality
return result;
}
}
So with this if you call a->publicComparator(b)' only when the type ofaandb` are the same will the derived function actually be executed, is that the functionality that you where looking for ?

Access base class fn with same signature from derived class object

Is it possible to access a base class function which has the same signature as that of a derived class function using a derived class object?. here's a sample of what I'm stating below..
class base1 {
public:
void test()
{cout<<"base1"<<endl;};
};
class der1 : public base1 {
public:
void test()
{cout<<"der1"<<endl;};
};
int main() {
der1 obj;
obj.test(); // How can I access the base class 'test()' here??
return 0;
}
You need to fully qualify the method name as it conflicts with the inherited one.
Use obj.base1::test()
You can't override a method in derived class if you didn't provide a virtual key word.
class base1
{
public:
void test()
{
cout << "base1" << endl;
};
};
class der1 : public base1
{
public:
void test()
{
cout << "der1" << endl;
};
};
int main()
{
der1 obj;
obj.test(); // How can I access the base class 'test()' here??
return 0;
}
So the above code is wrong. You have to give:
virtual void test();
in your base class
You can use this:
((base)obj).test();