I have a base class called Base which defines a virtual function. The class Derived now inherits from it and implements/overwrites that virtual function. The following code works just fine:
Base* pB = new Derived();
pB->virtual_function(); // function of class Derived gets called -> good
My problem is, that I now store all my derived instances in a STL container std::map<ID, Base*>. This seems to cause problems, because when I later iterate over that container and try for each Base* to call my virtual function, the runtime only recognizes the pointers as type Base* and does not call the overridden implementation in the class Derived.
Is there a way to get that working as intended or am I missing a crucial point here?
EDIT 1: Some additional code was requested, so here we go:
std::map<ComponentType, Base*> m_Components;
// The factory instantiates a Derived* (via functors) and returns it as Base*
Base* pB = m_pComponentFactory->createComponent(this, type);
// Lazy insert (since there is no map entry with key 'type' at that stage)
m_Components[type] = pB;
[...]
Base* pB;
for(ComponentMap::const_iterator it = m_Components.begin(); it != m_Components.end( ); ++it)
{
pB = it->second;
pB->virtual_function(); // goes to Base instead of Derived
}
EDIT 2: One thing I just realized is that I do not call dynamic_cast (or something similar) after creating the Derived instance via the functor (but I wouldn't know what to cast it to anyway since it is all generic/dynamic). It is just a return creator() with creator being the functor. Is that the issue?
Definition of creator type (the functon type):
typedef Base*(*ComponentCreator)([some params]);
Edit 3:
The actual functor is for example defined like this (Renderable and Location being derived classes from Base):
&Renderable::Create<Renderable> // or
&Location::Create<Location>
with the Create() method being a template function in the class Base.
template<typename T>
static Component* Create([some params])
{
return new T([some params]);
}
EDIT 4:
The problems seems to be my clone() + CopyConstructor handling. My clone currently looks like this:
Base* Base::clone() const
{
return new Base(*this);
}
Since I only create a Base*, the virtual resolution later on cannot work. The problem I am now left with though, is that I a missing an idea how to change the cloning. As shown in EDIT 1 I have my m_Components map with Base* pointers. I now need to clone them but I only know that they are of Base* and not of which exact derivative. One idea that comes to mind, might be to store functor used to create the Derived instance in the first place in the class, to reuse it later. So my clone would look something like this:
Base* Component::clone() const
{
return m_pCreationFunctor([some params]);
}
Anyone seeing a better approach?
You are a victim of slicing. When you copy construct a Base, you will lose the Derived parts of the object. See http://en.wikipedia.org/wiki/Object_slicing for a bit more detail. If the base class is not supposed to be instantiated, you might consider making it abstract to prevent making this mistake in future.
The fix in this case is probably to have a virtual Base * clone() method and override it in derived classes.
i.e.
class Base{
...
virtual Base * clone() const = 0;
...
};
class Derived : public Base {
...
Base * clone() const override { return new Derived(*this); }
...
};
If you really want to avoid rewriting the clone method, you could use an intermediate CRTP class i.e
struct Base{
virtual Base * clone() = 0;
};
template <typename D>
struct B : public Base {
virtual Base * clone() { return new D(*static_cast<D*>(this)); }
};
struct D : public B<D>{};
Related
I am trying to create an abstract class template (InstanceTracker) that classes can inherit from if they need functionality to perform operations on all of their instances. The class holds a static vector of pointers to 'T', and every time an InstanceTracker constructor is run, I push back a new pointer to the vector. I do this through a purely virtual getDerivedPtr() method that returns 'T*', that every class that derives from InstanceTracker has to implement with return this;. You can probably already see what is wrong what this though. You can never call a purely virtual function from a base constructor - since it doesn't exist yet. How can I find a way around this problem for my InstanceTracker class? Here's the code for the class:
#pragma once
#include <vector>
template <typename T>
class InstanceTracker
{
public:
InstanceTracker() noexcept
{
allInstances_.push_back(getDerivedPtr());
}
InstanceTracker(const InstanceTracker& source) noexcept
: InstanceTracker()
{
}
InstanceTracker(const InstanceTracker&& source) noexcept
: InstanceTracker()
{
}
virtual ~InstanceTracker() noexcept
{
auto it = std::find(allInstances_.begin(), allInstances_.end(), this);
int index = it - allInstances_.begin();
allInstances_.erase(allInstances_.begin() + index);
}
virtual T* getDerivedPtr() = 0;
protected:
static std::vector<T*> allInstances_;
};
If you want to try to run the code and see why it doesn't work at the moment, here's a simple class that inherits from InstanceTracker:
class Derived1 : public InstanceTracker
{
public:
Derived1* getDerivedPtr() override
{
return this;
}
};
You'd probably be better off using composition rather than inheritance, but I'll assume you have have a good reason to prefer inheritance here.
The difficulty is that, when a base class constructor is run, the this pointer is a pointer to an instance of the base class only. The derived instance doesn't even exit yet. (Likewise, on destruction, the derived portion of the object has already been uninitialized). So if you call a virtual method, you'll get the base class implementation rather than the derived class's implementation. In your case, the base class implementation doesn't even exist, so you're stuck.
You can probably get away with casting the base class's this pointer to a pointer to the derived class, but that's not guaranteed to work and probably involves undefined behavior.
One way to solve this is to store pointers to the base type (InstanceTracker *) rather the pointers to the derived type. Then your getDerivedPtr method doesn't need to be virtual, and it can do the cast when it's safe.
template <typename T>
class InstanceTracker {
public:
InstanceTracker() noexcept {
allInstances_.push_back(this);
}
// other constructors elided for space
virtual ~InstanceTracker() noexcept {
std::erase(
std::remove(allInstances_.begin(), allInstances_.end(),
this),
allInstances.end());
}
T* getDerivedPtr() {
return static_cast<T*>(this); // downcast
}
protected:
// allInstances_ stores base class pointers
static std::vector<InstanceTracker*> allInstances_;
};
Notes:
If you use RTTI, run-time type identification, you can use dynamic_cast instead of static_cast. You should not use a reinterpret_cast because the compiler might need to adjust the base pointer as part of the cast.
You're likely to run into problems if you create an instance of a derived type as const.
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.
How can I get derived class object from my generic interface pointer.
I do not want to type cast the generic interface in order to achieve above .
e.g:
class Base {}; // Has pure virtual functions and is my interface class
class Derived : public Base {}; // Additional functions .
Base *b = new Derived();
Now, I want to get derived pointer Derived *derived from b without casting.
How can I achieve this?
Your setup seems strange, I'd look for alternative options like returning Derived directly or moving the functions you need into base since you seem to need them.
If you still want to do that you could have something like:
class Derived; // Forward declaration
class Base {
public:
virtual Derived* as_derived() { return null; }
...
};
class Derived : public Base {
public:
Derived* as_derived() override { return this; }
};
Still, this looks like a hack and I would suggest casting instead. At least casting it's a common pattern and it will be easier for others to understand.
I have an abstract class that 3 other classes inherit from that and they are concrete classes. I have a pointer of type abstract class. I want to write a function, which receives an object of one of the 3 classes I mentioned, and then allocate memory for that (with base class pointer) and then assign the value of passed object to it. How can I new memory for that special type in my function?
(I don't know the type of the object I have received. I only know it inherits from my abstract class)
thanks.
The way I would solve this problem is that I would add a duplicate() method to the abstract base class, and I would implement it in each of the derived classes. Each implementation knows exactly how large it is, so it can use new to allocate the memory. It also knows exactly what content it has, so it can assign its value to the new instance. Nice, simple, elegant. and object-oriented.
There are two options for you.
Clone an object of the derived type.
Create a default-constructed object of the derived type.
Both of them can be implemented using virtual member functions.
You can see C++: Deep copying a Base class pointer on how to clone an object.
You can follow a similar path to return a default-constructed object.
struct base {
virtual ~base() {} // Remember to provide a virtual destructor
virtual base* make_new() const = 0;
};
struct derived : base {
virtual derived* make_new() const {
return new derived(); // Return a default-constructed object.
}
};
Add then call make_new() on the pointer.
The usual way of solving it is to add a clone member function that each class overrides. That can be a bit boiler-plate-ish however, so if you aren't afraid of templates you can automate the process:
#include <iostream>
#include <memory>
struct Abstract {
virtual ~Abstract() = default;
virtual std::unique_ptr<Abstract> clone() const = 0;
virtual void speak() const = 0;
};
template<class C>
struct Cloneable : Abstract {
std::unique_ptr<Abstract> clone() const override {
return std::make_unique<C>(*(C*)this);
}
};
struct Concrete : Cloneable<Concrete> {
void speak() const override {
std::cout << "Concrete";
}
};
void foo(Abstract& a) {
a.clone()->speak();
}
int main() {
Concrete c;
foo(c);
return 0;
}
Live Example
It works out of the box for copy-able classes. And if your class isn't copy-able, you can just override clone yourself, and do the thing that makes sense.
I have been struggling with this kind of problem for a long time, so I decided to ask here.
class Base {
virtual ~Base();
};
class Derived1 : public Base { ... };
class Derived2 : public Base { ... };
...
// Copies the instance of derived class pointed by the *base pointer
Base* CreateCopy(Base* base);
The method should return a dynamically created copy, or at least store the object on stack in some data structure to avoid "returning address of a temporary" problem.
The naive approach to implement the above method would be using multiple typeids or dynamic_casts in a series of if-statements to check for each possible derived type and then use the new operator.
Is there any other, better approach?
P.S.: I know, that the this problem can be avoided using smart pointers, but I am interested in the minimalistic approach, without a bunch of libraries.
You add a virtual Base* clone() const = 0; in your base class and implement it appropriately in your Derived classes. If your Base is not abstract, you can of course call its copy-constructor, but that's a bit dangerous: If you forget to implement it in a derived class, you'll get (probably unwanted) slicing.
If you don't want to duplicate that code, you can use the CRTP idiom to implement the function via a template:
template <class Derived>
class DerivationHelper : public Base
{
public:
virtual Base* clone() const
{
return new Derived(static_cast<const Derived&>(*this)); // call the copy ctor.
}
};
class Derived1 : public DerivationHelper <Derived1> { ... };
class Derived2 : public DerivationHelper <Derived2> { ... };
An alternative is to have a pure virtual CreateCopy() method in the common base that is implemented in each derived class.