Question regarding polymorphiic functions in C++ - c++

I am new to C++ and currently I am studying polymorphism.
I have this code:
#include <iostream>
class Base
{
public:
void say_hello()
{
std::cout << "I am the base object" << std::endl;
}
};
class Derived: public Base
{
public:
void say_hello()
{
std::cout << "I am the Derived object" << std::endl;
}
};
void greetings(Base& obj)
{
std::cout << "Hi there"<< std::endl;
obj.say_hello();
}
int main(int argCount, char *args[])
{
Base b;
b.say_hello();
Derived d;
d.say_hello();
greetings(b);
greetings(d);
return 0;
}
Where the output is:
I am the base object
I am the Derived object
Hi there
I am the base object
Hi there
I am the base object
This is not recognizing the polymorphic nature in the greetings functions.
If I put the virtual keyword in the say_hello() function, this appears to work as expected and outputs:
I am the base object
I am the Derived object
Hi there
I am the base object
Hi there
I am the Derived object
So my question is:
The polymorphic effect is retrieved when using a pointer/reference?
When I see tutorials they will present something like:
Base* ptr = new Derived();
greetings(*ptr);
And I was wondering if had to always resort to pointers when using polymorphism.
Sorry if this question is too basic.

For polymorphic behavior you need 2 things:
a virtual method overridden in a derived class
an access to a derived object via a base class pointer or reference.
Base* ptr = new Derived();
Those are bad tutorials. Never use owning raw pointers and explicit new/delete. Use smart pointers instead.

Just add a virtual declaration to the method to allow it to be overridden when using references to the base class:
virtual void say_hello() {...}
in both classes (or at least just the base class).

Related

Derived Class Pointer Pointing To Base Class Object Using Static_Cast [duplicate]

This question already has answers here:
Downcasting using the 'static_cast' in C++
(3 answers)
Closed 3 years ago.
I have the below piece of code where I have a base class and a derived class. Both base class and derived class are having a function member sharing the same name. In the main(), I have typecasted a base class object to a derived class pointer and trying to call the function. To my utter surprise, it is calling the derived class function member. As far as I know, the base class object won't be having any information about the derived class object. So, how come my derived class pointer is still able to access the derived member function?
In the case of upcasting, I do understand derived class object will be having the contents of the base class that's why a base class pointer pointing to a derived class object will work as expected.
Can someone please help me in understanding how the derived class member function is getting called in this even when I am having a derived class pointer pointing to a base class object(which is having no information of derived class)?
#include<iostream>
using namespace std;
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
public:
void b()
{
cout << "derived";
}
};
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
d1->b();
return 0;
}
In your specific case, it's perfectly normal that b is called.
You have a pointer to Derived class, b it's not virtual. So the compiler will generate a call to Derived::b method.
Now, when b will be executed, as you put crap in the this pointer, it's undefined behavior.
But in your case, as you do not access the this pointer, there's no probleme.
Cast a base class to derived class results undefined behavior
As I know, the function doesn't takes any extra space in memory, it stores like the normal function. You can see a member function as a normal function with an extra this pointer. In general, which function to call is determined by the type of the object pointer. But the virtual function is different, it is called by virtual function table, in your code, there is no virtual function declared. So there is no virtual function table.
You can see your code in a different way:
void derived_b(derived* this)
{
cout << "derived";
}
void base_b(base* this)
{
cout << "base";
}
int main()
{
base b;
derived * d1;
d1 =static_cast<derived*>(&b);
derived_b(d1);
return 0;
}
If you define some member in class, and use it in function b, it may cause some error.like
class base
{
public:
void b()
{
cout << "base";
}
};
class derived:public base
{
int a;
public:
derived(){a = 1;}
void b()
{
cout << "derived" << a;
}
};
your code in main() may cause error because the object b don't have any member in memory.

Is it possible to change a C++ object's class after instantiation?

I have a bunch of classes which all inherit the same attributes from a common base class. The base class implements some virtual functions that work in general cases, whilst each subclass re-implements those virtual functions for a variety of special cases.
Here's the situation: I want the special-ness of these sub-classed objects to be expendable. Essentially, I would like to implement an expend() function which causes an object to lose its sub-class identity and revert to being a base-class instance with the general-case behaviours implemented in the base class.
I should note that the derived classes don't introduce any additional variables, so both the base and derived classes should be the same size in memory.
I'm open to destroying the old object and creating a new one, as long as I can create the new object at the same memory address, so existing pointers aren't broken.
The following attempt doesn't work, and produces some seemingly unexpected behaviour. What am I missing here?
#include <iostream>
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
};
class Derived : public Base {
public:
void whoami() {
std::cout << "I am Derived\n";
}
};
Base* object;
int main() {
object = new Derived; //assign a new Derived class instance
object->whoami(); //this prints "I am Derived"
Base baseObject;
*object = baseObject; //reassign existing object to a different type
object->whoami(); //but it *STILL* prints "I am Derived" (!)
return 0;
}
You can at the cost of breaking good practices and maintaining unsafe code. Other answers will provide you with nasty tricks to achieve this.
I dont like answers that just says "you should not do that", but I would like to suggest there probably is a better way to achieve the result you seek for.
The strategy pattern as suggested in a comment by #manni66 is a good one.
You should also think about data oriented design, since a class hierarchy does not look like a wise choice in your case.
Yes and no. A C++ class defines the type of a memory region that is an object. Once the memory region has been instantiated, its type is set. You can try to work around the type system sure, but the compiler won't let you get away with it. Sooner or later it will shoot you in the foot, because the compiler made an assumption about types that you violated, and there is no way to stop the compiler from making such assumption in a portable fashion.
However there is a design pattern for this: It's "State". You extract what changes into it's own class hierarchy, with its own base class, and you have your objects store a pointer to the abstract state base of this new hierarchy. You can then swap those to your hearts content.
No it's not possible to change the type of an object once instantiated.
*object = baseObject; doesn't change the type of object, it merely calls a compiler-generated assignment operator.
It would have been a different matter if you had written
object = new Base;
(remembering to call delete naturally; currently your code leaks an object).
C++11 onwards gives you the ability to move the resources from one object to another; see
http://en.cppreference.com/w/cpp/utility/move
I'm open to destroying the old object and creating a new one, as long as I can create the new object at the same memory address, so existing pointers aren't broken.
The C++ Standard explicitly addresses this idea in section 3.8 (Object Lifetime):
If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object <snip>
Oh wow, this is exactly what you wanted. But I didn't show the whole rule. Here's the rest:
if:
the storage for the new object exactly overlays the storage location which the original object occupied, and
the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).
So your idea has been thought of by the language committee and specifically made illegal, including the sneaky workaround that "I have a base class subobject of the right type, I'll just make a new object in its place" which the last bullet point stops in its tracks.
You can replace an object with an object of a different type as #RossRidge's answer shows. Or you can replace an object and keep using pointers that existed before the replacement. But you cannot do both together.
However, like the famous quote: "Any problem in computer science can be solved by adding a layer of indirection" and that is true here too.
Instead of your suggested method
Derived d;
Base* p = &d;
new (p) Base(); // makes p invalid! Plus problems when d's destructor is automatically called
You can do:
unique_ptr<Base> p = make_unique<Derived>();
p.reset(make_unique<Base>());
If you hide this pointer and slight-of-hand inside another class, you'll have the "design pattern" such as State or Strategy mentioned in other answers. But they all rely on one extra level of indirection.
I suggest you use the Strategy Pattern, e.g.
#include <iostream>
class IAnnouncer {
public:
virtual ~IAnnouncer() { }
virtual void whoami() = 0;
};
class AnnouncerA : public IAnnouncer {
public:
void whoami() override {
std::cout << "I am A\n";
}
};
class AnnouncerB : public IAnnouncer {
public:
void whoami() override {
std::cout << "I am B\n";
}
};
class Foo
{
public:
Foo(IAnnouncer *announcer) : announcer(announcer)
{
}
void run()
{
// Do stuff
if(nullptr != announcer)
{
announcer->whoami();
}
// Do other stuff
}
void expend(IAnnouncer* announcer)
{
this->announcer = announcer;
}
private:
IAnnouncer *announcer;
};
int main() {
AnnouncerA a;
Foo foo(&a);
foo.run();
// Ready to "expend"
AnnouncerB b;
foo.expend(&b);
foo.run();
return 0;
}
This is a very flexible pattern that has at least a few benefits over trying to deal with the issue through inheritance:
You can easily change the behavior of Foo later on by implementing a new Announcer
Your Announcers (and your Foos) are easily unit tested
You can reuse your Announcers elsewhere int he code
I suggest you have a look at the age-old "Composition vs. Inheritance" debate (cf. https://www.thoughtworks.com/insights/blog/composition-vs-inheritance-how-choose)
ps. You've leaked a Derived in your original post! Have a look at std::unique_ptr if it is available.
You can do what you're literally asking for with placement new and an explicit destructor call. Something like this:
#include <iostream>
#include <stdlib.h>
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
};
class Derived : public Base {
public:
void whoami() {
std::cout << "I am Derived\n";
}
};
union Both {
Base base;
Derived derived;
};
Base *object;
int
main() {
Both *tmp = (Both *) malloc(sizeof(Both));
object = new(&tmp->base) Base;
object->whoami();
Base baseObject;
tmp = (Both *) object;
tmp->base.Base::~Base();
new(&tmp->derived) Derived;
object->whoami();
return 0;
}
However as matb said, this really isn't a good design. I would recommend reconsidering what you're trying to do. Some of other answers here might also solve your problem, but I think anything along the idea of what you're asking for is going to be kludge. You should seriously consider designing your application so you can change the pointer when the type of the object changes.
You can by introducing a variable to the base class, so the memory footprint stays the same. By setting the flag you force calling the derived or the base class implementation.
#include <iostream>
class Base {
public:
Base() : m_useDerived(true)
{
}
void setUseDerived(bool value)
{
m_useDerived = value;
}
void whoami() {
m_useDerived ? whoamiImpl() : Base::whoamiImpl();
}
protected:
virtual void whoamiImpl() { std::cout << "I am Base\n"; }
private:
bool m_useDerived;
};
class Derived : public Base {
protected:
void whoamiImpl() {
std::cout << "I am Derived\n";
}
};
Base* object;
int main() {
object = new Derived; //assign a new Derived class instance
object->whoami(); //this prints "I am Derived"
object->setUseDerived(false);
object->whoami(); //should print "I am Base"
return 0;
}
In addition to other answers, you could use function pointers (or any wrapper on them, like std::function) to achieve the necessary bevahior:
void print_base(void) {
cout << "This is base" << endl;
}
void print_derived(void) {
cout << "This is derived" << endl;
}
class Base {
public:
void (*print)(void);
Base() {
print = print_base;
}
};
class Derived : public Base {
public:
Derived() {
print = print_derived;
}
};
int main() {
Base* b = new Derived();
b->print(); // prints "This is derived"
*b = Base();
b->print(); // prints "This is base"
return 0;
}
Also, such function pointers approach would allow you to change any of the functions of the objects in run-time, not limiting you to some already defined sets of members implemented in derived classes.
There is a simple error in your program. You assign the objects, but not the pointers:
int main() {
Base* object = new Derived; //assign a new Derived class instance
object->whoami(); //this prints "I am Derived"
Base baseObject;
Now you assign baseObject to *object which overwrites the Derived object with a Base object. However, this does work well because you are overwriting an object of type Derived with an object of type Base. The default assignment operator just assigns all members, which in this case does nothing. The object cannot change its type and still is a Derived objects afterwards. In general, this can leads to serious problems e.g. object slicing.
*object = baseObject; //reassign existing object to a different type
object->whoami(); //but it *STILL* prints "I am Derived" (!)
return 0;
}
If you instead just assign the pointer it will work as expected, but you just have two objects, one of type Derived and one Base, but I think you want some more dynamic behavior. It sounds like you could implement the specialness as a Decorator.
You have a base-class with some operation, and several derived classes that change/modify/extend the base-class behavior of that operation. Since it is based on composition it can be changed dynamically. The trick is to store a base-class reference in the Decorator instances and use that for all other functionality.
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
virtual void otherFunctionality() {}
};
class Derived1 : public Base {
public:
Derived1(Base* base): m_base(base) {}
virtual void whoami() override {
std::cout << "I am Derived\n";
// maybe even call the base-class implementation
// if you just want to add something
}
virtual void otherFunctionality() {
base->otherFunctionality();
}
private:
Base* m_base;
};
Base* object;
int main() {
Base baseObject;
object = new Derived(&baseObject); //assign a new Derived class instance
object->whoami(); //this prints "I am Derived"
// undecorate
delete object;
object = &baseObject;
object->whoami();
return 0;
}
There are alternative patterns like Strategy which implement different use cases resp. solve different problems. It would probably good to read the pattern documentation with special focus to the Intent and Motivation sections.
I would consider regularizing your type.
class Base {
public:
virtual void whoami() { std::cout << "Base\n"; }
std::unique_ptr<Base> clone() const {
return std::make_unique<Base>(*this);
}
virtual ~Base() {}
};
class Derived: public Base {
virtual void whoami() overload {
std::cout << "Derived\n";
};
std::unique_ptr<Base> clone() const override {
return std::make_unique<Derived>(*this);
}
public:
~Derived() {}
};
struct Base_Value {
private:
std::unique_ptr<Base> pImpl;
public:
void whoami () {
pImpl->whoami();
}
template<class T, class...Args>
void emplace( Args&&...args ) {
pImpl = std::make_unique<T>(std::forward<Args>(args)...);
}
Base_Value()=default;
Base_Value(Base_Value&&)=default;
Base_Value& operator=(Base_Value&&)=default;
Base_Value(Base_Value const&o) {
if (o.pImpl) pImpl = o.pImpl->clone();
}
Base_Value& operator=(Base_Value&& o) {
auto tmp = std::move(o);
swap( pImpl, tmp.pImpl );
return *this;
}
};
Now a Base_Value is semantically a value-type that behaves polymorphically.
Base_Value object;
object.emplace<Derived>();
object.whoami();
object.emplace<Base>();
object.whoami();
You could wrap a Base_Value instance in a smart pointer, but I wouldn't bother.
I don’t disagree with the advice that this isn’t a great design, but another safe way to do it is with a union that can hold any of the classes you want to switch between, since the standard guarantees it can safely hold any of them. Here’s a version that encapsulates all the details inside the union itself:
#include <cassert>
#include <cstdlib>
#include <iostream>
#include <new>
#include <typeinfo>
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
virtual ~Base() {} // Every base class with child classes that might be deleted through a pointer to the
// base must have a virtual destructor!
};
class Derived : public Base {
public:
void whoami() {
std::cout << "I am Derived\n";
}
// At most one member of any union may have a default member initializer in C++11, so:
Derived(bool) : Base() {}
};
union BorD {
Base b;
Derived d; // Initialize one member.
BorD(void) : b() {} // These defaults are not used here.
BorD( const BorD& ) : b() {} // No per-instance data to worry about!
// Otherwise, this could get complicated.
BorD& operator= (const BorD& x) // Boilerplate:
{
if ( this != &x ) {
this->~BorD();
new(this) BorD(x);
}
return *this;
}
BorD( const Derived& x ) : d(x) {} // The constructor we use.
// To destroy, be sure to call the base class’ virtual destructor,
// which works so long as every member derives from Base.
~BorD(void) { dynamic_cast<Base*>(&this->b)->~Base(); }
Base& toBase(void)
{ // Sets the active member to b.
Base* const p = dynamic_cast<Base*>(&b);
assert(p); // The dynamic_cast cannot currently fail, but check anyway.
if ( typeid(*p) != typeid(Base) ) {
p->~Base(); // Call the virtual destructor.
new(&b) Base; // Call the constructor.
}
return b;
}
};
int main(void)
{
BorD u(Derived{false});
Base& reference = u.d; // By the standard, u, u.b and u.d have the same address.
reference.whoami(); // Should say derived.
u.toBase();
reference.whoami(); // Should say base.
return EXIT_SUCCESS;
}
A simpler way to get what you want is probably to keep a container of Base * and replace the items individually as needed with new and delete. (Still remember to declare your destructor virtual! That’s important with polymorphic classes, so you call the right destructor for that instance, not the base class’ destructor.) This might save you some extra bytes on instances of the smaller classes. You would need to play around with smart pointers to get safe automatic deletion, though. One advantage of unions over smart pointers to dynamic memory is that you don’t have to allocate or free any more objects on the heap, but can just re-use the memory you have.
DISCLAIMER: The code here is provided as means to understand an idea, not to be implemented in production.
You're using inheritance. It can achieve 3 things:
Add fields
Add methods
replace virtual methods
Out of all those features, you're using only the last one. This means that you're not actually forced to rely on inheritance. You can get the same results by many other means. The simplest is to keep tabs on the "type" by yourself - this will allow you to change it on the fly:
#include <stdexcept>
enum MyType { BASE, DERIVED };
class Any {
private:
enum MyType type;
public:
void whoami() {
switch(type){
case BASE:
std::cout << "I am Base\n";
return;
case DERIVED:
std::cout << "I am Derived\n";
return;
}
throw std::runtime_error( "undefined type" );
}
void changeType(MyType newType){
//insert some checks if that kind of transition is legal
type = newType;
}
Any(MyType initialType){
type = initialType;
}
};
Without inheritance the "type" is yours to do whatever you want. You can changeType at any time it suits you. With that power also comes responsibility: the compiler will no longer make sure the type is correct or even set at all. You have to ensure it or you'll get hard to debug runtime errors.
You may wrap it in inheritance just as well, eg. to get a drop-in replacement for existing code:
class Base : Any {
public:
Base() : Any(BASE) {}
};
class Derived : public Any {
public:
Derived() : Any(DERIVED) {}
};
OR (slightly uglier):
class Derived : public Base {
public:
Derived : Base() {
changeType(DERIVED)
}
};
This solution is easy to implement and easy to understand. But with more options in the switch and more code in each path it gets very messy. So the very first step is to refactor the actual code out of the switch and into self-contained functions. Where better to keep than other than Derivied class?
class Base {
public:
static whoami(Any* This){
std::cout << "I am Base\n";
}
};
class Derived {
public:
static whoami(Any* This){
std::cout << "I am Derived\n";
}
};
/*you know where it goes*/
switch(type){
case BASE:
Base:whoami(this);
return;
case DERIVED:
Derived:whoami(this);
return;
}
Then you can replace the switch with an external class that implements it via virtual inheritance and TADA! We've reinvented the Strategy Pattern, as others have said in the first place : )
The bottom line is: whatever you do, you're not inheriting the main class.
you cannot change to the type of an object after instantiation, as you can see in your example you have a pointer to a Base class (of type base class) so this type is stuck to it until the end.
the base pointer can point to upper or down object doesn't mean changed its type:
Base* ptrBase; // pointer to base class (type)
ptrBase = new Derived; // pointer of type base class `points to an object of derived class`
Base theBase;
ptrBase = &theBase; // not *ptrBase = theDerived: Base of type Base class points to base Object.
pointers are much strong, flexible, powerful as much dangerous so you should handle them cautiously.
in your example I can write:
Base* object; // pointer to base class just declared to point to garbage
Base bObject; // object of class Base
*object = bObject; // as you did in your code
above it's a disaster assigning value to un-allocated pointer. the program will crash.
in your example you escaped the crash through the memory which was allocated at first:
object = new Derived;
it's never good idea to assign a value and not address of a subclass object to base class. however in built-in you can but consider this example:
int* pInt = NULL;
int* ptrC = new int[1];
ptrC[0] = 1;
pInt = ptrC;
for(int i = 0; i < 1; i++)
cout << pInt[i] << ", ";
cout << endl;
int* ptrD = new int[3];
ptrD[0] = 5;
ptrD[1] = 7;
ptrD[2] = 77;
*pInt = *ptrD; // copying values of ptrD to a pointer which point to an array of only one element!
// the correct way:
// pInt = ptrD;
for(int i = 0; i < 3; i++)
cout << pInt[i] << ", ";
cout << endl;
so the result as not as you guess.
I have 2 solutions. A simpler one that doesn't preserve the memory address, and one that does preserve the memory address.
Both require that you provide provide downcasts from Base to Derived which isn't a problem in your case.
struct Base {
int a;
Base(int a) : a{a} {};
virtual ~Base() = default;
virtual auto foo() -> void { cout << "Base " << a << endl; }
};
struct D1 : Base {
using Base::Base;
D1(Base b) : Base{b.a} {};
auto foo() -> void override { cout << "D1 " << a << endl; }
};
struct D2 : Base {
using Base::Base;
D2(Base b) : Base{b.a} {};
auto foo() -> void override { cout << "D2 " << a << endl; }
};
For the former one you can create a smart pointer that can seemingly change the held data between Derived (and base) classes:
template <class B> struct Morpher {
std::unique_ptr<B> obj;
template <class D> auto morph() {
obj = std::make_unique<D>(*obj);
}
auto operator->() -> B* { return obj.get(); }
};
int main() {
Morpher<Base> m{std::make_unique<D1>(24)};
m->foo(); // D1 24
m.morph<D2>();
m->foo(); // D2 24
}
The magic is in
m.morph<D2>();
which changes the held object preserving the data members (actually uses the cast ctor).
If you need to preserve the memory location, you can adapt the above to use a buffer and placement new instead of unique_ptr. It is a little more work a whole lot more attention to pay to, but it gives you exactly what you need:
template <class B> struct Morpher {
std::aligned_storage_t<sizeof(B)> buffer_;
B *obj_;
template <class D>
Morpher(const D &new_obj)
: obj_{new (&buffer_) D{new_obj}} {
static_assert(std::is_base_of<B, D>::value && sizeof(D) == sizeof(B) &&
alignof(D) == alignof(B));
}
Morpher(const Morpher &) = delete;
auto operator=(const Morpher &) = delete;
~Morpher() { obj_->~B(); }
template <class D> auto morph() {
static_assert(std::is_base_of<B, D>::value && sizeof(D) == sizeof(B) &&
alignof(D) == alignof(B));
obj_->~B();
obj_ = new (&buffer_) D{*obj_};
}
auto operator-> () -> B * { return obj_; }
};
int main() {
Morpher<Base> m{D1{24}};
m->foo(); // D1 24
m.morph<D2>();
m->foo(); // D2 24
m.morph<Base>();
m->foo(); // Base 24
}
This is of course the absolute bare bone. You can add move ctor, dereference operator etc.
#include <iostream>
class Base {
public:
virtual void whoami() {
std::cout << "I am Base\n";
}
};
class Derived : public Base {
public:
void whoami() {
std::cout << "I am Derived\n";
}
};
Base* object;
int main() {
object = new Derived;
object->whoami();
Base baseObject;
object = &baseObject;// this is how you change.
object->whoami();
return 0;
}
output:
I am Derived
I am Base
Your assignment only assigns member variables, not the pointer used for virtual member function calls. You can easily replace that with full memory copy:
//*object = baseObject; //this assignment was wrong
memcpy(object, &baseObject, sizeof(baseObject));
Note that much like your attempted assignment, this would replace member variables in *object with those of the newly constructed baseObject - probably not what you actually want, so you'll have to copy the original member variables to the new baseObject first, using either assignment operator or copy constructor before the memcpy, i.e.
Base baseObject = *object;
It is possible to copy just the virtual functions table pointer but that would rely on internal knowledge about how the compiler stores it so is not recommended.
If keeping the object at the same memory address is not crucial, a simpler and so better approach would be the opposite - construct a new base object and copy the original object's member variables over - i.e. use a copy constructor.
object = new Base(*object);
But you'll also have to delete the original object, so the above one-liner won't be enough - you need to remember the original pointer in another variable in order to delete it, etc. If you have multiple references to that original object you'll need to update them all, and sometimes this can be quite complicated. Then the memcpy way is better.
If some of the member variables themselves are pointers to objects that are created/deleted in the main object's constructor/destructor, or if they have a more specialized assignment operator or other custom logic, you'll have some more work on your hands, but for trivial member variables this should be good enough.

Is it possible to creat a derived object from a base object through downcast?

Base class
class Base
{
public:
Base()=default;
virtual void f(){cout << "base class\n";}
virtual ~Base(){}
};
Derived class
class Derive : public Base
{
public:
Derive()=default;
void f() override {cout << "derived class\n";}
};
main function
int main()
{
Base* bsd = new Base;
Derive* dru = new Derive;
if(Derive* drd=dynamic_cast<Derive*>(bsd)){
drd->f();
cout << "downcast successful\n";
}else{
cout << "downcast failed\n";
}
if(Base* bsu=dynamic_cast<Base*>(dru)){
bsu->f();
cout << "upcast successful\n";
}else{
cout << "upcast failed\n";
}
delete bsd;
delete dru;
}
It turns out upcast works fine, while downcast failed. It seems makes sense that way. If the derived class contain member objects that are not declared in the base class and do not have default constructors, what gonna happen during downcast?
Besides, the target pointer *drd(*bsd) created through dynamic_cast points to the same object with the pointer *bsu(*dru) to be cast. So delete once will be enough. We will not have a dangling pointer, right?
Casting does not create anything new or changes objects in any way. Casting changes the interpretation of an existing object, so if an object is not a Derive, there is no way to make it a Derive through casting.
Note that Derive is also a Base, because inheriting creates an "is a" relationship. That's why upcasting works: all it does is telling the compiler that it should treat the pointed to object as Base, even though the object is actually Derive.
It makes no difference in your program, so here is an illustration of what the cast does:
class Derive : public Base
{
public:
Derive()=default;
void f() override {cout << "derived class\n";}
void added() {cout << "hello" << endl; }
};
dru->added(); // Works
Base* bsu=dynamic_cast<Base*>(dru);
bsu->added(); // Does not compile
Essentially, the cast "hides" added interfaces from the compiler, ordering it to treat a Derive object as if it were Base. Of course, the overrides continue to be called correctly, because the overriden member-functions are part of the Base's interface.
I'm not sure I got your question right, but yes, you can safely delete a derived class using a base pointer, if the destructor is virtual.
A "dangling pointer" is something different: After you have deleted bsd and dru, you can not use these pointers anymore, they have become dangling pointers, because they point to deleted memory that you don't own anymore.
dynamic_cast checks run-time type check and provides a safe conversion. If a meaningful conversion is possible then you'd get a valid object after downcast. As you pointed out, in your example the underlying object was of "base class". Run time type check failed. However if the underlying object was of "derieved class" dynamic_cast would have succeeded. ex:
class CBase
{
public:
CBase(void);
virtual ~CBase(void);
virtual void identify()
{
std::cout << "base class" << std::endl;
}
};
class CDerieved : public CBase
{
public:
CDerieved(void);
virtual ~CDerieved(void);
virtual void identify()
{
std::cout << "Derieved class" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
CDerieved* pderieved = new CDerieved;
pderieved->identify();
CBase* pb = static_cast<CBase*>(pderieved);
pb->identify();
CDerieved* pd1 = dynamic_cast<CDerieved*>(pb);
pd1->identify();
return 0;
}
The above code will succeed.
But please remember, if you find needing a downcast, then the design needs to be revised.

C++ - Dynamic Binding and Object Instances Not Accessing Derived Methods

I haven't written anything in C++ in quite some time, and am running into some inheritance issues that are confusing.
First question - From my understanding, a base class with a virtual method whose derived class implements that method should call the derived method IF the method is called from a pointer to the base class. Why does it need to be a pointer? Is this because of the way vtables are implemented? If so, why is an implementation detail not abstracted in the actual specification? I am trying to understand why this is the case. Is there a time when you want the base class to be called, only if the object is not a pointer? I thought the point was for pointers to objects to behave similarly to those objects.
Second question - In the below code, I ran a test to see that derived class methods were called if the method of access was a pointer. Then, I went back and tried to use the same method to turn the instance into a pointer to achieve the same binding. However, there is no cast that will allow me to use the class as a derived class if it was, at any point, stored as an object instance. Why is this? If, for example, I took the same objects (further below) and put them in a vector then it works correctly.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class BaseClass {
public:
virtual void A();
virtual void B();
};
void BaseClass::A() {
cout << "In base A" << endl;
}
void BaseClass::B() {
cout << "In base B" << endl;
}
class DerivedClass1 : public BaseClass {
public:
void A();
void B();
};
void DerivedClass1::A() {
cout << "In Derived A" << endl;
}
void DerivedClass1::B() {
cout << "In Derived B" << endl;
}
int main(int argc, char** argv) {
string cmd;
BaseClass bc;
DerivedClass1 dc1;
vector<BaseClass> list;
list.push_back(bc);
list.push_back(dc1);
cout << "Calling by " << endl;
for(int i = 0; i < list.size(); i++) {
// There is no possible cast to BaseClass* that causes A or B to call the derived class
(dynamic_cast<BaseClass*>(&list[i]))->A();
(dynamic_cast<BaseClass*>(&list[i]))->B();
}
// However, the below code, although it stores the same addresses, etc. works fine.
vector<BaseClass*> list_ptrs;
list_ptrs.push_back(&bc);
list_ptrs.push_back(&dc1);
cout << "Outputting Pointers" << endl;
for(int i = 0; i < list_ptrs.size(); i++) {
list_ptrs[i]->A();
list_ptrs[i]->B();
}
getline(cin, cmd);
}
Sorry if I am just misunderstanding something very basic, but it seems to be an inconsistency in the way that dynamic binding works, and I can't find a decent explanation (all Google returns are people trying to access base class methods...).
Any assistance would be appreciated,
Thanks,
-Alex
This is wrong:
BaseClass bc;
DerivedClass1 dc1;
vector<BaseClass> list;
list.push_back(bc);
list.push_back(dc1);
Your vector can only store BaseClass objects. Trying to stuff a DerivedClass into something that can only hold BaseClass objects is termed as object slicing, which you do not want happen. Object slicing means just that -- you are "slicing off" the DerivedClass's attributes so that it is a BaseClass.
Either have a vector of BaseClass pointers, or two separate vectors, one of BaseClass objects, the other of DerivedClass objects.
vector<BaseClass*> theList;
theList.push_back(&bc);
theList.push_back(&dc1);
You should now see the virtual functions work as expected.

Virtual keyword use in C++

I understand that C++ implements runtime polymorphism thorugh virtual functions and that virtual keyword is inherited but I don't see use of virtual keyword in derived class.
e.g. In below case even if you dropped virtual keyword in derived class still ptr->method() call goes to derived::method. So what extra this virtual keyword is doing in derived class?
#include<iostream>
using namespace std;
class base
{
public:
virtual void method()
{
std::cout << std::endl << "BASE" << std::endl;
}
};
class derived: public base
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED" << std::endl;
}
};
int main()
{
base* ptr = new derived();
ptr->method();
return 9;
}
If the method of the derived class matches a virtual method of one of the base classes by name and signature, and the matched method is virtual, then the method of a derived class becomes virtual as well. So, technically, there is no need to mark such methods as «virtual» in derived classes. However, before C++11 it used to be a good practice just because it is a great hint to those reading the code (it could be hard to keep in mind all of the virtual functions of base class(es)).
Starting with C++11, there are two additional keywords for doing this in the derived classes that help both readability and code robustness. They are «override» and «final». For example, putting «override» in a derived class`s method ensures that a corresponding method of a base class is, in fact, virtual. The «final» keyword does the same plus it prevents the method from being further overriden.
I also wrote about this with more real-world rationales and code examples in my blog, here.
Hope it helps. Good Luck!
Nothing. Just to help remind you what functions are virtual or not.
virtual is only necessary in the base class declaration. It's optional in the derived class(es), and probably serves mostly as a reminder in those cases.
C++11 introduces override to make things even more explicit : it explicitely marks a method in a derived class as being an override of a virtual method of a base class.
Implicitly virtual methods in derived classes are virtual in derived classes, no need to explicitly define them virtual.If you declare it will be redundant declaration.
ptr->method();
When the compiler came across the above statement
-> It will try to resolve the above statement, as the method() function is virtual, compiler postpone the resolving of that call to run time.
->As you created the object of derived class at run time, now the compiler will get to know that this method is of derived class.
what extra this virtual keyword is doing in derived class?
Consider this scenario there is one more derived class called Derived2 inherting form derived and it has its own virtual method.
class derived2: public derived
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED2" << std::endl;
}
};
If you call the method() in main like below
int main()
{
base* ptr = new derived2();
ptr->method(); //derived2 class method() will get called
return 9;
}
If the method() in derived2 is not virtual by default, you will end up calling teh derived version of method(), loosing the benefit of runtime polymorphism.
Hence the authors of c++ did a wonderful job here, by making the virtual key word inheritance hierarchical.
virtual keyword is optional in drive class because according to the rule when you drive a class with the base class which have virtual function and when you override the virtual function in drive class compiler implicitly assign virtual keyword along with the function. So you not need to explicitly assign the virtual keyword. But this keyword is necessary during multilevel inheritance.
Example:
In your code we add this code.
class derived: public base {
public:
virtual void method() { // In this line virtual keyword is optional.
std::cout << std::endl << "DERIVED :: method function" << std::endl;
}
virtual void display() {
std::cout << std::endl << "DERIVED :: display function" << std::endl;
}
};
class deriveChild: public derived {
public:
void method() {
std::cout << std::endl << "DERIVECHILD :: method" << std::endl;
}
void display() {
std::cout << std::endl << "DERIVECHILD:: display" << std::endl;
}
};
In the main() if you use below code it will give you different output.
base *ptr = new deriveChild();
ptr->method(); // will compile and execute
ptr->display(); // will generate error because display() is not part of base class.
Now if you want to use display() of deriveChild class then use this code.
derived *ptr = new deriveChild();
ptr->method(); // Compile and Execute
ptr->display(); // Compile and Execute