Store derived in base assignement then call base function - c++

I am from Java and a bit new to C++.
In Java I would have the possibility to do this: link to code
I create an abstract base class Mother, with one pure virtual function used in a public function of that same base class.
I tried this :
class Mother {
private:
virtual void bar() = 0;
public:
void foo();
};
void Mother::foo() {
// ... some code
bar();
}
class Child0: public Mother {
private:
void bar();
};
void Child0::bar() {
std::cout << "Child0" << std::endl;
}
class Child1: public Mother {
private:
void bar();
};
void Child1::bar() {
std::cout << "Child1" << std::endl;
}
// main code
int main() {
Mother mother;
if(condition) {
Child0 child;
mother = child;
} else {
Child1 child;
mother = child;
}
mother.foo();
}
But I get a compiler error:
main.cpp:35:12: fatal error: variable type 'Mother' is an abstract class
Mother mother;
^
main.cpp:5:22: note: unimplemented pure virtual method 'bar' in 'Mother'
virtual void bar() = 0;
^
What am I missing?

C++, unlike Java, has value semantics and no implicit pointers: when you declare Mother mother; you get an actual instance of Mother. No more, no less. Except in your case, where Mother is abstract: you can't have an instance of Mother!
Doing mother = child; later just assigns the Mother part of the child into mother. This is called "object slicing", because the child part you expected to copy as well is sliced off.
To fix this, you need to use either pointers or references, which can both refer to objects whose dynamic type differ from their static type (e.g, a Mother that is actually a Child0). I'll use the simplest owning pointer, std::unique_ptr:
int main() {
std::unique_ptr<Mother> mother;
if(condition) {
mother = std::make_unique<Child0>();
} else {
mother = std::make_unique<Child1>();
}
// At this point, *mother is of static type Mother,
// but of dynamic type Child0 or Child1.
mother->foo();
}
Note that I have also switched to dynamic allocation: Your two children instances were automatic variables, which means that they die at the end of their scope {}. std::make_unique constructs an object with dynamic lifetime: it will only die when the unique_ptr holding it does.
As noted in the other answer, since your child object will be destructed polymorphically, through the type of Mother, Mother's destructor should be virtual to be dispatched correctly.
class Mother {
// ...
public:
virtual ~Mother() = default;
};

You are missing the object slicing trap, and also have undefined behavior: when you assign
mother = child;
child gets "sliced" down to mother, with any polymorphic behavior removed.
If you wish to retain polymorphism, use pointers:
Mother *mother;
if(condition) {
mother = new Child0;
} else {
mother = new Child1;
}
mother->foo();
delete mother;
Make sure Mother has a virtual destructor.
Note that you can no longer use objects from inner scope, because the pointer would become invalid as soon as the scope ends:
// Do not do this!
Mother *mother;
if(condition) {
Child0 child;
mother = &child;
}
mother->foo(); // <<<=== This is undefined behavior

Related

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.

C++ Add derived object of abstract class into another class without dangling pointers?

I have a simple container class that points to an abstract class and I have functions to get/set the pointer in the container class. More concretely, the class looks like this:
class Container
{
Abstract* thing;
public:
void set(Abstract &obj)
{
thing = &obj; //danger of dangling pointer
}
Abstract* get()
{
return thing;
}
};
Abstract is an abstract class. As can be seen already, there's a danger of a dangling pointer. I know that I could make a copy of the object (new) and then point to it. But I can't create an instance of an abstract class. What solutions to this are there?
The following are just more information:
Class definitions
class Abstract
{
public:
virtual void something() = 0;
};
class Base : public Abstract
{
int a;
public:
Base() {}
Base(int a) : a(a){}
virtual void something()
{
cout << "Base" << endl;
}
};
class Derived : public Base
{
int b;
public:
Derived() {}
Derived(int a, int b) : Base(a), b(b){}
virtual void something()
{
cout << "Derived" << endl;
}
};
Simple tests
void setBase(Container &toSet)
{
Base base(15);
toSet.set(base);
}
void setDerived(Container &toSet)
{
Derived derived(10, 30);
toSet.set(derived);
}
int main()
{
Container co;
Base base(15);
Derived derived(10, 30);
Base *basePtr;
Derived *derivedPtr;
//This is fine
co.set(base);
basePtr = static_cast<Base *>(co.get());
basePtr->something();
//This is fine
co.set(derived);
derivedPtr = static_cast<Derived *>(co.get());
derivedPtr->something();
//Reset
basePtr = nullptr;
derivedPtr = nullptr;
//Dangling pointer!
setBase(co);
basePtr = static_cast<Base *>(co.get());
basePtr->something();
//Dangling pointer!
setDerived(co);
derivedPtr = static_cast<Derived *>(co.get());
derivedPtr->something();
return 0;
}
What you need to do is to define your memory ownership concretely.
Container::set accepts an instance of Abstract by reference, which usually does not imply an ownership transfer:
void set(Abstract &obj){...} // Caller retains ownership of obj, but now we have a weak reference to it
Then the onus of deletion is not on you.
Container::get returns a pointer which implies ownership, indicating that someone who calls set should not invalidate the passed object.
Abstract* get(){...}
This could be problematic, as you've stated.
You have a few options
Encode these memory ownership semantics within Container with proper documentation (Code by contract)
Use a smart pointer like std::shared_ptr
In the former case, whether it works or not depends on the user reading and understanding your API, and then behaving nicely with it. In the latter case, the pointer object owns itself, and will delete the allocated memory when the last instance goes out of scope.
void set(std::shared_ptr<Abstract> obj){...}
// now Container participates in the lifetime of obj,
// and it's harder to nullify the underlying object
// (you'd have to be intentionally misbehaving)
If you are worried about the object being deallocated elsewhere resulting in a dangling pointer, you could use boost smart pointers.
Boost smart pointers would provide you the service of book keeping and help to avoid such a case.
Some information can be found here :
smart pointers (boost) explained
This is what std::unique_ptr is for:
class Container
{
std::unique_ptr<Abstract> thing;
public:
void set(std::unique_ptr<Abstract> obj)
{
thing = obj;
}
Abstract* get()
{
return thing.get();
}
};
Now the Abstract object is "owned" by Container and will be cleaned up automatically when the Conatiner is destroyed.
If you want a pointer that might live longer, or might be shared between mulitple containers, use std::shared_ptr instead.

Why does "this" change in parent of class with multiple base classes?

(Initial note: this question is not the same question as whether or not it is safe to delete a void pointer, though that issue has some relation to the problem identified in Update 2. The question here is why a base class obtains a different value from this than is obtained by the derived class for the same object. In cases where the derived object will call a suicide method of the base class, the base class must have a virtual destructor, and the pointer being deleted must be of type pointer-to-base class; storing it in a void* isn't a safe way to delete an object from a base class method.)
I have a diamond-shaped multiple inheritance where my child class has two parents that both inherit from the same grand-parent, thus:
class Grand
class Mom : public virtual Grand
class Dad : public Grand
class Child : Mom, Dad
I wrote Mom and Child, but Grand and Dad are library classes I didn't write (that's why Mom inherits virtually from Grand, but Dad doesn't).
Mom implements a pure virtual method declared in Grand. Dad does not. Therefore, Child also implements that same method (because otherwise the compiler would object that Dad's declaration of that method, inherited by Child, had no implementation). Child's implementation merely calls Mom's implementation. Here's the code (I've included code for Dad and Grand, as this is a SSCCE, not the code I'm stuck using that relies on library classes I didn't write):
class Grand
{
public:
virtual void WhoAmI(void) = 0;
};
class Mom : public virtual Grand
{
public:
virtual void WhoAmI()
{
void* momThis = this;
}
//virtual int getZero() = 0;
};
class Dad : public Grand
{
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
return Mom::WhoAmI();
}
int getZero()
{
return 0;
}
};
int main()
{
Child* c = new Child;
c->WhoAmI();
return 0;
}
Note that the getZero method in Child is never called.
Stepping through execution with the debugger, I see that the address in Child* c is 0x00dcdd08. Stepping into Child::WhoAmI, I see that the address in void* childThis is also 0x00dcdd08, which is what I expect. Stepping further into Mom::WhoAmI, I see that void* momThis is assigned 0x00dcdd0c, which I interpret to be the address of the Mom subobject of my multiply inherited Child object (but I admit I'm a bit out of my depth at this point).
Okay, the fact that Child's this and Mom's this are different doesn't shock me. Here's what does: if I uncomment the declaration of getZero in Mom, and step through all of that again, Mom::this and Child::this are the same!
How can the addition of virtual int getZero() = 0 to the Mom class result in the Mom subobject and the Child object having the same address? I thought maybe the compiler recognized that all of Mom's methods were virtual and its vtable was the same as Child's, so they somehow became the "same" object, but adding more, and different, methods to each class doesn't change this behavior.
Can anyone help me understand what governs when this is the same for the parent and child of a multiply inherited child and when it is different?
Update
I've tried to simplify things to focus as narrowly as I can on the issue of when this has a different value in a parent object than it has in that parent's child object. To do that, I've changed the inheritance to make it a true diamond, with Dad and Mom both inheriting virtually from Grand. I've eliminated all virtual methods and no longer need to specify which parent class's method I am calling. Instead, I have a unique method in each parent class that will let me use the debugger to see what value this has in each parental object. What I see is that this is the same for one parent and the child, but different for the other parent. Moreover, which parent has the different value changes when the order of the parents is changed in the child's class declaration.
This turns out to have catastrophic consequences if either of the parent objects tries to delete itself. Here's code that, on my machine, runs fine:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x0137dd0c
}
};
class Dad : public virtual Grand
{
public:
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x0137dd08
delete dadIam; // this works
}
};
class Child : Dad, Mom
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x0137dd08
c->WhoAmI();
return 0;
}
However, if I change class Child : Dad, Mom to class Child : Mom, Dad, it crashes at run-time:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
This is a problem when you have a class that includes methods that can delete objects of that class (a "suicide method"), and those methods might be called from derived classes.
But, I think I have found the solution: any base class that includes a method that might delete instances of itself and that might have those methods called from instances of classes derived from that class must have a virtual destructor.
Adding one to the code above make the crash go away:
class Grand
{
};
class Mom : public virtual Grand
{
public:
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
virtual ~Dad() {};
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
A number of people I've met are aghast at the idea of an object deleting itself, but it is legal and a necessary idiom when implementing COM's IUnknown::Release method. I found good guidelines on how to use delete this safely, and some equally good guidelines on using virtual destructors to solve this problem.
I note, however, that unless the person who coded your parent class coded it with a virtual destructor, calling any suicide method of that parent class from an instance of a class derived from that parent is probably going to crash, and do so unpredictably. Perhaps a reason to include virtual destructors, even when you don't think you need one.
Update 2
Well, the problem comes back if you add a virtual destructor to both Dad and Mom. This code crashes when it attempts to delete Dad's this pointer, which does not match Child's this pointer:
class Grand
{
};
class Mom : public virtual Grand
{
public:
virtual ~Mom() {};
void WhosYourMommy()
{
void* momIam = this; // momIam == 0x013bdd08
}
};
class Dad : public virtual Grand
{
public:
virtual ~Dad() {};
void WhosYourDaddy()
{
void* dadIam = this; // dadIam == 0x013bdd0c
delete dadIam; // this crashes
}
};
class Child : Mom, Dad
{
public:
virtual ~Child() {};
void WhoAmI()
{
void* childThis = this;
WhosYourMommy();
WhosYourDaddy();
return;
}
};
int main()
{
Child* c = new Child; // c == 0x013bdd08
c->WhoAmI();
return 0;
}
Update 3
Thanks to BeyelerStudios for asking the right question: deleting a void* instead of deleting a Dad* prevented C++ from knowing what it was really deleting and, therefore, stopped it from calling the virtual destructors of the base and derived classes. Replacing delete dadIam with delete this solves that problem, and the code runs fine.
Although it would be somewhat ridiculous, replacing delete dadIam with delete (Dad*)dadIam also runs fine, and helps illustrate that the type of the pointer operated on by delete makes a difference to what delete does. (Something I should hardly find surprising in a polymorphic language.)
BeyelerStudios, if you want to post that as an answer, I'll check the box for you.
Thanks!
As mentioned by the standard [intro.object]:
Objects can contain other objects, called subobjects. A subobject can be [...] a base class subobject [...].
Moreover [expr.prim.this]:
The keyword this names a pointer to the object for which a non-static member function is invoked [...].
It goes without saying that two different classes (derived and base) are different objects, thus can have different values for the this pointer.
Can anyone help me understand what governs when this is the same for the parent and child of a multiply inherited child and when it is different?
When and why they differ is not ruled by the standard (of course, it's mainly due to the existence of a vtable associated to the object, but please note that vtables are simply a common, convenient way to deal with polymorphism and the standard never mentions them).
It usually derives from the chosen/implemented ABI (see here for further details about a common one, the Itanium C++ ABI).
It follows a minimal, working example to reproduce the case:
#include<iostream>
struct B {
int i;
void f() { std::cout << this << std::endl; }
};
struct D: B {
void f() { std::cout << this << std::endl; }
virtual void g() {}
};
int main() {
D d;
d.f();
d.B::f();
}
An example output is:
0xbef01ac0
0xbef01ac4

Polymorpishm in C++

I am studying inheritance and polymorphism in C++ and I came across this example:
class Parent
{
public:
void a()
{
std::cout << "parentA";
}
virtual void b()
{
std::cout<<"parentB";
}
};
class Child : public Parent
{
public:
void b()
{
std::cout<<"childB";
}
};
Then in main:
int main()
{
Parent i= Child();
i.b(); //why doesn't this give parentB?
Parent *j= new Child();
j->b();
}
The outputs are parentA and childB respectively but I can't understand why. (isn't b() overriding?)
The first case should give parentB, since the object i has type Parent, not Child. The Child object is sliced - that is, its Parent subobject is copied to create i of type Parent, then the temporary Child is destroyed. You can often prevent confusing behaviour like this by making base classes abstract (that is, giving them pure virtual functions), so that they can't be instantiated.
The second case should give childB, since the object that j points to has dynamic type Child.
You have "sliced" the Child class into the Parent class. In order to access virtual methods, you need to store the instance polymorphically, like you have with your second example. Polymorphic variables are pointers and references.

How to call child object's overloading function in polymorphism?

Consider the following simple polymorphism ...
class Parent {
public:
someFunc() { /* implementation A */ };
};
class Child : public Parent {
public:
someFunc() { /* implementation B */ };
};
int main ()
{
Parent* ptr;
ptr = new Parent();
ptr->someFunc();
delete ptr;
ptr = new Child();
ptr->someFunc();
delete ptr;
return 0;
}
As far as I can tell, in both cases implementation A will be called.
How can I call the "most derived" implementation of someFunc, depending on the dynamic type of ptr?
In my real code there are many children types, so it wouldn't be practical to use dynamic_cast to check per child class.
Try:
class Parent
{
public:
virtual someFunc() { /* implementation A */ };
//^^^^^^^
};
Though technically not required.
I always find it good style to also declare the derived function virtual:
class Child : public Parent
{
public:
virtual someFunc() { /* implementation B */ };
};
Unlike Java functions are not virtual by default.
Declare someFunc virtual. This will ensure that the implementation of the actual object is called, not the implementation depending on the pointer type.
This will, however, add some overhead connected with the creation of the VTABLE and slower calling of the virtual function, but is essentially what polymorphism is.
There is no polymorphism here! None of your functions are virtual.
If you want polymorphism, do this:
class Parent {
public:
virtual someFunc() { /* implementation A */ };
};