I am trying to get my Base class instance and cast it to the derived class type. Since I can only get a const reference of my base class instance, I struggle to get it cast correctly. Does anyone have an idea?
class Base
{
};
class Derived : public Base
{
};
Base someBaseInstance;
const Base& GetBase()
{
return someBaseInstance;
}
int main()
{
Derived& derived = static_cast<Base&>(GetBase());
return 0;
}
You must declare your instance as a Derived object. It can be referenced and passed as it's Base, but must be declared as Derived:
Derived someDerivedInstance;
Also, to convert between Base and Derived, you should use dynamic_cast<>:
Derived &derived = dynamic_cast<Derived&>(GetBase());
Related
class Base1{
public:
Base1(){};
virtual ~Base1() = 0;
}
class Derived1 : public Base1{
public:
Derived1(int a) : a(a){};
~Derived1();
int a;
}
class Base2{
public:
Base2(){};
virtual ~Base2() = 0;
}
class Derived2 : public Base2{
public:
Derived2(int b) : b(b){};
~Derived2();
int b;
void func(const Base1 &base1); // How to access Derived1::a here?
}
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? I am still new to polymorphism. I tried to use different static_cast or dynamic_cast methods but none of them works. What should I do inside the function so I can access a derived class member from a base class reference?
FYI I can't change the class definition for my coursework requirement, and that is what given to me. I understand that it is simpler to just pass Derived1 as parameter but I am not allow to do so.
Given the above class definition, how can I access Derived1::a in void func(const Base1 &base1)? ... FYI I can't change the class definition for my coursework requirement, and that is what given to me.
Ideally, you should expose a virtual method in Base1 that returns an int (or int&), and then have Derived1 override that method to return its a member.
But, given that you are not allowed to change the class definitions, that is not an option.
You need a pointer or reference to a Derived1 object in order to access its a member directly. Which really leaves you with only 1 choice - you can use dynamic_cast to typecast the base class reference to the derived class type, eg:
void Derived2::func(const Base1 &base1)
{
// this will raise an exception if the cast fails at runtime
const Derived1 &d = dynamic_cast<const Derived1&>(base1);
// use d.a as needed...
}
Alternatively:
void Derived2::func(const Base1 &base1)
{
// this will return null if the cast fails at runtime
const Derived1 *d = dynamic_cast<const Derived1*>(&base1);
if (d) {
// use d->a as needed...
} else {
// do something else...
}
}
Let's say I have a base class and 2 derived classes:
class Base {
public:
Base() : m_base(0) { }
private:
int m_base;
};
class Derived1 : public Base {
public:
Derived1() : Base(), m_d1(1) { }
private:
int m_d1;
};
class Derived2 : public Base {
public:
Derived2(): Base(), m_d2(2.5) { }
private:
double m_d2;
};
I now want an overloaded constructor to construct an instance of Derived2 by initializing its base part by an instance of Derived1 where I came across some different approaches:
Pointer to Derived1 + dynamic_cast + base class copy-constructor within initializer list:
Derived2(Derived1 *d1) : Base(*(dynamic_cast<Base*>(d1))), m_d2(3.5) { }
Obviously this has the problem of de-referencing an invalid pointer
Reference to Base and cast Derived1 when calling:
Derived2(const Base &base) : Base(base), m_d2(3.5) { }
// ...
Derived1 d1 = Derived1();
Derived2 d2 = Derived2(static_cast<Base>(d1));
Call default constructor of Base first and then initialize every single member:
Derived2(Derived *d1) : Base(), m_d2(3.5) {
if (d1) {
m_base = d1->base();
}
}
But this needs access to the members of Derived1 as well as the members of Base to be protected
Most certainly there is another better way - So which is the best way to achieve this and why?
Pointer to Derived1 + dynamic_cast + base class copy-constructor within initializer list
There is no need for pointers, no need for dynamic casting, and no need to limit the argument to only Derived1.
Reference to Base and cast Derived1 when calling
This is fine, except the cast is redundant. An object is implicitly convertible to its base.
Call default constructor of Base first and then initialize every single member
This is pointlessly complicated, and will not be an option in cases where base is not default initialisable.
Another alternative is to pass the base by value, and move from it:
Derived2(Base base) : Base(std::move(base))
This allows avoiding a copy from rvalue arguments. That won't be particularly useful for the trivial Base in the example, but can be much faster for some real example that is slow to copy.
You don't need to cast to a base type.
The most direct translation of what you say you want to do is
Derived2(const Derived1& d1): Base(d1), m_d2(2.5) { }
and then all you need is
Derived1 d1;
Derived2 d2(d1);
If you want to accept any type derived from Base:
Derived2(const Base& b): Base(b), m_d2(2.5) { }
Suppose we have classes Derived* (here * means distinguishing suffixes), which are derived from class Base. Now a member should be added into class Base, the type of which needs to be differently inherited of its own type in derived classes. It could be represented as following (in logic) in c++:
class Base {
protected:
BaseType m_member;
};
class Derived1 : Base {
DerivedType1 m_member; // this member should be the same member in base class
};
class Derived2 : Base {
DerivedType2 m_member;
};
class BaseType {
protected:
virtual void foo();
};
class DerivedType1 : BaseType { ... };
class DerivedType2 : BaseType { ... };
Here m_member in Derived1 is meant to be exactly m_member in Base, with only types changed (and even the new type is inherited from the old type). I know that this piece of code does not do what I need (here m_members in each class are not related with each other at all), what do I need to do?
I've considered using boost::static_visitor (and without creating new classes for Base) for this case. However, derived classes needs to be classes.
Now my temporary solution for this problem is that derived classes hold this member of the same type as the base classes, but handle this member in different ways. Source:
class Base {
protected:
BaseType m_member;
};
class Derived1 : Base {
public:
Derived1() :
m_member(DerivedType1()) { /* ... */ }
};
So, any better choices? E.g. pointers?
If I have a base class and a derived class, such as:
class Base {
protected:
int a;
public:
void setA(int);
void getA(int);
}
class Derived : public Base {
private:
int b;
public:
void doThing();
}
Then a third, additional class that uses the base class:
class OtherClass {
public:
Base doClassThing(Base*, Base*);
}
What's the best way to pass the derived class to a function that's defined to return a base class and take the base class as an argument. Like this:
Derived *x = new Derived();
Derived *y = new Derived();
doClassThing(x, y);
Would I pass the objects with a type cast? Or should I type cast the objects when they're first created?
To answer your two questions:
You would not cast the objects when they're first created.
There is no need to cast when calling; You do not need to modify the code in your question.
I have following
class base
{
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};
now I have
base* pbase = new derived();
pbase->myFunc();
I am getting error myFunc is not a member function of base.
How to avoid this? and how to make myFunc get called?
Note I should have base class contain no function as it is part of design and above code is part of big function
If you are adamant that this function should NOT be a part of base, you have but 2 options to do it.
Either use a pointer to derived class
derived* pDerived = new derived();
pDerived->myFunc();
Or (uglier & vehemently discouraged) static_cast the pointer up to derived class type and then call the function
NOTE: To be used with caution. Only use when you are SURE of the type of the pointer you are casting, i.e. you are sure that pbase is a derived or a type derived from derived. In this particular case its ok, but im guessing this is only an example of the actual code.
base* pbase = new derived();
static_cast<derived*>(pbase)->myFunc();
myfunc needs to be accessible from the base class, so you would have to declare a public virtual myfunc in base. You could make it pure virtual if you intend for base to be an abstract base class, i.e one that cannot be instantiated and acts as an interface:
class base
{
public:
virtual void myfunc() = 0; // pure virtual method
};
If you ant to be able to instantiate base objects then you would have to provide an implementation for myfunc:
class base
{
public:
virtual void myfunc() {}; // virtual method with empty implementation
};
There is no other clean way to do this if you want to access the function from a pointer to a base class. The safetest option is to use a dynamic_cast
base* pbase = new derived;
....
derived* pderived = dynamic_cast<derived*>(pbase);
if (derived) {
// do something
} else {
// error
}
To use the base class pointer, you must change the base class definition to be:
class base
{
public:
virtual void myFunc() { }
};
I see no other way around it. Sorry.
You could add it as a member of base and make it a virtual or pure virtual function. If using this route however, you should also add a virtual destructor in the base class to allow successful destruction of inherited objects.
class base
{
public:
virtual ~base(){};
virtual void myFunc() = 0;
};
class derived : public base
{
public:
derived() {}
void myFunc() { cout << "My derived function" << std::endl; }
};