Changing a class to its child class - c++

I'm trying to make each instance of a class (named Caller here) have an instance of another class (Target). The point is that the second class has numerous children and I need to be able to have the Caller class switch among them at will. I have tried several ways, but not one gave me any desirable results. Current code:
class Target
{
public:
virtual void do_something()
{ log_message("NO!"); }
};
class TargetChild : public Target
{
public:
virtual void do_something()
{ log_message("YES!"); }
};
class Caller
{
private:
Target target;
public:
void call_target()
{ target.do_something(); }
void set_target(Target set_target)
{ target = set_target; }
};
int main( int argc, const char* argv[] )
{
TargetChild targetChild;
Caller caller;
caller.call_target();
caller.set_target(targetChild);
caller.call_target();
}
The wanted result in the log file is "NO! YES!" but instead it writes the NO! twice. I can't really see what's wrong with it.

You cannot change the type of an object in C++. You can only create, destroy, copy, and (in C++11) move data. In this case, you've copied the data from the subclass object to the base class object. This copied an empty subset of an empty subset. The problem you observed is called "slicing."
Probably what you want is a member containing a function pointer that can be changed. virtual gets you a function pointer but it can't be changed. Try std::tr1::function, boost::function or C++11 std::function.
Or, if you really want to go the virtual route, use a Target * pointer. Best to use a smart pointer class such as unique_ptr< Target > (again Boost/TR1/C++11) or std::auto_ptr< Target > (old-fashioned C++03). You can also do it yourself with new and delete, but such code doesn't really work as well, and is only suitable for a little educational tinkering.

Your code is suffering from object slicing. Even though targetChild in main is a TargetChild, it's passed by value to Caller::set_target, which means it's copied to a local variable which has type Target. To get around object slicing in general, you must use pass-by-reference or use pointers.
In this case, since you wish for Caller to access the passed object outside the Caller::set_target method, you should use a pointer. References alone won't work because though you could make Caller::target a reference, you couldn't change the object it referred to.
Pointers introduce memory management problems, as you must ensure the TargetChild is deallocated (otherwise the program has a memory leak), but not too soon (which will cause access violations, most likely crashing your program). The boost library has various smart pointer classes to make this easier. The C++ standard auto_ptr class could also be used, if only one other class should own the TargetChild instance at any one point in time.

Use an interface, ITarget and switch them at will
ITarget
virtual void do_something() { log_message("NO!"); }
Treat everything as Type of ITarget
This a neat way of handling it.
My c++ is rusty :)

Use pointers instead. More about polymorphism: http://www.cplusplus.com/doc/tutorial/polymorphism/
...
class Caller
{
private:
Target* target;
public:
Caller() { target = NULL; }
void call_target() { if (target != NULL) target->do_something(); }
void set_target(Target* set_target) { target = set_target; }
};
int main( int argc, const char* argv[] )
{
....
caller.set_target(&targetChild);
...
}

In set_target you are passing targetChild by value, there you are loosing the chance to call TargetChild::do_something. You need to extend caller to include a reference (or pointer) to the current target, the reference (or pointer) will keep the information about the original TargetChild and then the compiler will still call TargetChild::do_something.

Related

Shared pointer inheritance without explicitly casting first

So, I am trying to do something like this
template <typename T>
void call(std::shared_ptr<Base<T>> b) {
}
int main() {
std::shared_ptr<Derived<int>> d = std::make_shared<Derived<int>>();
call(d);
}
It cant resolve the inheritance because they are shared pointers. Ideally I don't want to use static_pointer_cast or something like that in main so I was looking for maybe a different way to cast it so that the user in main can still call the same function but not have to worry about casting.
My second approach was to use raw pointers so I tried something like this:
template <typename T>
void call(Base<T> * b) {
std::shared_ptr<Base<T>> obj(b);
}
int main() {
std::shared_ptr<Derived<int>> d = std::make_shared<Derived<int>>();
call(d.get());
}
Since Base is an abstract class I can't use make_shared so I have to do it this way to my knowledge but the problem then becomes that as soon as the call function's scope ends it deletes the pointer resulting in a double free error since the shared ptr in main also tries to delete this.
Are there any suggestions for something to try?
First, it is a bad practice to use smart pointers wherever the ownership is not needed. In your case the main function owns the pointer, and there is no way the object is destroyed while the call function is being executed. So you may pass a raw pointer without problems (and that is even better because the interface doesn't require more than it needs). This however may not be true in case of multithreaded environment or if the call function has side effects storing the pointer (e.g. that is actually a set method if a class). In this case shared_ptr should be used indeed.
Next, you may create a shared_ptr<Base> initializing it with a pointer to Derived. You even don't need to have virtual destructor for deleting the object: shared_ptr knows the actual type:
{
std::shared_ptr<Base> d = std::make_shared<Derived>();
// Ok to delete
}
Finally, there is no problem in casting shared_ptr<Derived> to shared_ptr<Base>. That is another instance of a shared pointer that points to the same counter.

How to populate interface for existing object?

I have an interface:
struct result {
virtual ~result() = 0;
virtual auto getName() -> std::string = 0;
protected:
result() = default;
result(const result &) = default;
auto operator=(const result &) -> result & = default;
}
and an implementation:
struct abstract_result : public result {
auto getName() -> std::string override;
std::string m_name;
}
I'm currently using an instance of abstract_result within my code to be populated by a number of algorithms but I want the end user to receive a pointer to the interface so I can hide the implementation.
How can I turn an instance of abstract_result into a std::unique_ptr<result>?
An abstract_result is-a result (btw your naming seems to be the wrong way around) so a pointer to a abstract_result is-a pointer to a result. So you just need to construct the unique_ptr, eg
auto x = unique_ptr<result>(new abstract_result());
In case the instance is on the stack and you are worried about unique_ptr trying to delete an instance with automaitc storage, you can use a deleter that does nothing, as in
template <typename T>
struct no_deleter {
void operator()(T*){}
};
abstract_result x;
std::unique_ptr<result> x_ptr{ &x, no_deleter<result>() };
However, in that case I wonder why you want to use a unique_ptr in the first place. There is nothing wrong about using raw pointers as long as they do not own the object (ie whoever holds the pointer is not responsible for deleting the object), while a unique_ptr is usually meant to own the object it points to.
PS
I have to admit that I dont fully understand what is your problem...
but I want to turn a populated instance of abstract_result into a
pointer to result
As mentioned above, a pointer to a abstract_result is (sloppy-speaking) already a pointer to a result. A simpler example:
abstract_result x;
result* pointer_to_result = &x;
If I understand you correctly, what you want to do is pretty similar to what #user463035818 says, but with the populated structure, i.e.:
std::unique_ptr<result> pointer_to_result {&my_populated_abstract_result };
And this is fine since, again, an abstract_result is-a result. But you might not want to do this at all if your my_populated_abstract_result is not dynamically allocated. std::unique_ptr is not generally intended for use with objects on the stack (e.g. local variables). If my_populated_abstract_result is a local variable - don't put in a unique_ptr at all (nor in an std::shared_ptr), and don't try to hold on to it once my_populated_abstract_result goes out of scope.
PS :
Doesn't it make more sense for the pure-virtual base class to be called abstract_result, with the concrete classes being foo_result, bar_result, baz_result?
Perhaps it's a good idea to use a namespace if you really have a lot of names with _result in them? That way you'll have result::abstract (or result::base) and then result::foo, result::bar, result::baz.

std::move with a unique pointer of a base class pointing to an instance of a derived class

I am attempting to implement the command and strategy design patterns in C++.
I have an interface for a command, and an interface for a strategy (a different strategy is assigned to each player, so a player may be manual, AI aggressive, AI defensive, AI random... etc). The strategies have a series of functions which return a unique pointer of type ICommand (eg the command interface) which point to an instance of a derived command class. The idea is to create some command in my strategy in a particular way, and then return the unique pointer to the particular command to the game (the invoker of commands) which execute the commands, regardless of what that command is.
My following questions are these:
if I move an instance of a derived class which is pointed to by a unique pointer of a base class, will I get object slicing?
if so, what would be a better way of handling moving around objects regardless of their type ?
Here is my code. Note that I only included the code for the command choose_combo, as the rest would be somewhat redundant:
I have an interface for my standard command:
class Igame_command {
protected: // protected, since Igame_command is an interface.
player &p;
game_model &gm;
Igame_command(player p, game_model gm) : p(p), gm(gm) {}
public:
virtual void execute() = 0;
};
I then have some derived class which implements the above interface:
class choose_combo_c : private Igame_command {
combo c;
int vp;
public:
void set_combo(combo c) { this->c = c; }
void set_vp(int vp) { this->vp = vp; }
combo get_combo() { return c; }
int get_vp() { return vp; }
choose_combo_c::choose_combo_c(player &p, game_model &gm);
void execute() override;
};
I then have an interface for my strategy:
class Istrategy {
protected:
application &app;
game_model &gm;
player &p;
Istrategy(application &app, game_model &gm, player &p) : app(app), gm(gm), p(p) {}
public:
virtual std::unique_ptr<Igame_command> choose_combo(
std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) = 0;
};
For example, for the manual strategy, choosing combo:
std::unique_ptr<Igame_command> manual_strategy::choose_combo(
std::vector<combo> &available_combos, std::vector<int> &available_combos_vp) override {
// code to have the player make a choice, it sets the int choice...
choose_combo_c* ccc = new choose_combo_c(p, gm);
ccc->set_combo(available_combos.at(choice));
ccc->set_vp(available_combos_vp.at(choice));
return std::unique_ptr<Igame_command> (new choose_combo_c(std::move(*ccc)));
}
unique_ptr<T> stores a T*, not a T, so you won't get any object slicing in your example.
But you do have a memory leak, the ccc object you allocate is not being deleted by anyone, you're move constructing a new object from it, but leaking the original itself. The code within manual_strategy::choose_combo should be written as
auto ccc = std::make_unique<choose_combo_c>(p, gm); // create a unique_ptr<choose_combo_c>
// do stuff with it
ccc->set_combo(available_combos.at(choice));
ccc->set_vp(available_combos_vp.at(choice));
// simply return it here, a unique_ptr<Igame_command>
// will be constructed from the unique_ptr<choose_combo_c>
return ccc;
You can't "move" raw pointers - not meaningfully, anyway. You can meaningfully move a unique_ptr, but that doesn't move the object anywhere, it only means that the ownership of that pointed-to object (as allocated memory) moves to someplace/someone else.
That's not what you're doing, though; your code moves your temporary object into a newly-allocated object (which causes a memory leak, as #Preatorian points out).
What would be a better way of handling moving around objects regardless of their type ?
Working with pointers is actually a reasonable way for doing object "moves" irrespective of their types: You simply never (or rarely) actually move any objects, you only work with pointers to them. You might not be able to use typed unique_ptrs if you want type-obliviousness, but you could use void * or unique_ptr<void> pointers with custom deleters.
Another alternative is to use std::any's, without pointers. If the objects are small, moving these is cheap, and if they're big, they're hiding pointers inside, so moving them is again cheap. This alternative in safer in the sense that instead of segmentation violation and reinterpreting garbage, you'll just get exceptions if you try the wrong type.

How to store different data types in one list? (C++)

I need to store a list of various properties of an object. Property consists of a name and data, which can be of any datatype.
I know I can make a class "Property", and extend it with different PropertySubClasses which only differ with the datatype they are storing, but it does not feel right.
class Property
{
Property(std::string name);
virtual ~Property();
std::string m_name;
};
class PropertyBoolean : Property
{
PropertyBoolean(std::string name, bool data);
bool m_data;
};
class PropertyFloat : Property
{
PropertyFloat(std::string name, float data);
float m_data;
};
class PropertyVector : Property
{
PropertyVector(std::string name, std::vector<float> data);
std::vector<float> m_data;
};
Now I can store all kinds of properties in a
std::vector<Property*>
and to get the data, I can cast the object to the subclass. Or I can make a pure virtual function to do something with the data inside the function without the need of casting.
Anyways, this does not feel right to create these different kind of subclasses which only differ by the data type they are storing. Is there any other convenient way to achieve similar behavior?
I do not have access to Boost.
C++ is a multi-paradigm language. It shines brightest and is most powerful where paradigms are mixed.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Why using std::shared_ptr<Property> instead of Property*?
Consider this code:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
That for loop there attempts to cleanup, deleting all the properties in the vector, just before it goes out of scope and takes all the pointers with it.
Now, while this might seem fine for a novice, if you're an only mildly experienced C++ developer, that code should raise alarm bells as soon as you look at it.
The problem is that the call to use_property_list() might throw an exception. If so, the function f() will be left right away. In order to properly cleanup, the destructors for all automatic objects created in f() will be called. That is, my_property_list will be properly destroyed. std::vector's destructor will then nicely cleanup the data it holds. However, it holds pointers, and how should std::vector know whether these pointers are the last ones referencing their objects?
Since it doesn't know, it won't delete the objects, it will only destroy the pointers when it destroys its content, leaving you with objects on the heap that you don't have any pointers to anymore. This is what's called a "leak".
In order to avoid that, you would need to catch all exceptions, clean up the properties, and the rethrow the exception. But then, ten years from now, someone has to add a new feature to the 10MLoC application this has grown to, and, being in a hurry, adds code which leaves that function prematurely when some condition holds. The code is tested and it works and doesn't crash - only the server it's part of now leaks a few bytes an hour, making it crash due to being out of memory about once a week. Finding that makes for many hours of fine debugging.
Bottom line: Never manage resources manually, always wrap them in objects of a class designed to handle exactly one instance of such a resource. For dynamically allocated objects, those handles are called "smart pointer", and the most used one is shared_ptr.
A lower-level way is to use a union
class Property
union {
int int_data;
bool bool_data;
std::cstring* string_data;
};
enum { INT_PROP, BOOL_PROP, STRING_PROP } data_type;
// ... more smarts ...
};
Dunno why your other solution doesn't feel right, so I don't know if this way would feel better to you.
EDIT: Some more code to give an example of usage.
Property car = collection_of_properties.head();
if (car.data_type == Property::INT_PROP) {
printf("The integer property is %d\n", car.int_data);
} // etc.
I'd probably put that sort of logic into a method of the class where possible. You'd also have members such as this constructor to keep the data and type field in sync:
Property::Property(bool value) {
bool_data = value;
data_type = BOOL_PROP;
}
I suggest boost::variant or boost::any. [Related question]
Write a template class Property<T> that derives from Property with a data member of type T
Another possible solution is to write a intermediate class managing the pointers to Property classes:
class Bla {
private:
Property* mp
public:
explicit Bla(Property* p) : mp(p) { }
~Bla() { delete p; }
// The standard copy constructor
// and assignment operator
// aren't sufficient in this case:
// They would only copy the
// pointer mp (shallow copy)
Bla(const Bla* b) : mp(b.mp->clone()) { }
Bla& operator = (Bla b) { // copy'n'swap trick
swap(b);
return *this;
}
void swap(Bla& b) {
using std::swap; // #include <algorithm>
swap(mp, b.mp);
}
Property* operator -> () const {
return mp;
}
Property& operator * () const {
return *mp;
}
};
You have to add a virtual clone method to your classes returning a pointer to a newly created copy of itself:
class StringProperty : public Property {
// ...
public:
// ...
virtual Property* clone() { return new StringProperty(*this); }
// ...
};
Then you'll be able to do this:
std::vector<Bla> v;
v.push_back(Bla(new StringProperty("Name", "Jon Doe")));
// ...
std::vector<Bla>::const_iterator i = v.begin();
(*i)->some_virtual_method();
Leaving the scope of v means that all Blas will be destroyed freeing automatically the pointers they're holding. Due to its overloaded dereferencing and indirection operator the class Bla behaves like an ordinary pointer. In the last line *i returns a reference to a Bla object and using -> means the same as if it was a pointer to a Property object.
A possible drawback of this approach is that you always get a heap operation (a new and a delete) if the intermediate objects must be copied around. This happens for example if you exceed the vector's capacity and all intermediate objects must be copied to a new piece of memory.
In the new standard (i.e. c++0x) you'll be able to use the unique_ptr template: It
can be used inside the standard containers (in contrast to the auto_ptr which must not be used in the standard containers),
offers the usually faster move semantics (it can easily passed around) and
takes care over the held pointers (it frees them automatically).
I see that there are lots of shots at trying to solve your problem by now, but I have a feeling that you're looking in the wrong end - why do you actually want to do this in the first place? Is there some interesting functionality in the base class that you have omitted to specify?
The fact that you'd be forced to switch on a property type id to do what you want with a specific instance is a code smell, especially when the subclasses have absolutely nothing in common via the base class other than a name (which is the type id in this case).
Starting with C++ 17 we have something called as std::variant and std::any.
std::variant
An instance of std::variant at any given time either holds a value of one of its alternative types, or in the case of error - no value.
std::any
The class any describes a type-safe container for single values of any copy constructible type.
An object of class any stores an instance of any type that satisfies the constructor requirements or is empty, and this is referred to as the state of the class any object. The stored instance is called the contained object. Two states are equivalent if they are either both empty or if both are not empty and if the contained objects are equivalent.
The non-member any_cast functions provide type-safe access to the contained object.
You can probably do this with the Boost library, or you could create a class with a type code and a void pointer to the data, but it would mean giving up some of the type safety of C++. In other words, if you have a property "foo", whose value is an integer, and give it a string value instead, the compiler will not find the error for you.
I would recommend revisiting your design, and re-evaluating whether or not you really need so much flexibility. Do you really need to be able to handle properties of any type? If you can narrow it down to just a few types, you may be able to come up with a solution using inheritance or templates, without having to "fight the language".

Ensuring pointer is not deleted

I've stumbled onto something I can't figure out, so I think I'm missing something in the greater C++ picture.
In short, my question is: how to keep a mutable, non-deletable, possibly NULL instance of an object in a class.
The longer version is:
I have the following scenario: a bunch of classes (which I can change slightly, but not thoroughly refactor), most of which need to use an object. This object, while mutable, is managed by someone else so it must not be deleted.
Some of the classes in the bunch do not need such an object - they reuse code from other classes, but through the available parameters supplied to these classes it is guaranteed that even if an object is supplied, it will not be used.
The current implementation uses a pointer-to-const-object (const Obj *). This, in turn, means all the object's methods must be const and most fields mutable. This is a messy solution since the fields declared mutable are available for inspection (so quite the opposite of the c++ lite entry here). It also only partially solves the "do-not-delete-this-here" issue (compiler does not complain but a const in front of the object is an indication).
If I used a reference to this object, I'd force some callers to create a "dummy" object and provide it to the class they are instantiating. This is also messy, besides being a waste of resources. I cannot create a global object to can stand in for a "NULL" reference due to project restrictions.
I feel that the reference is the tool I need, but I cannot refactor the classes involved to such an extent as to have the object disappear from their implementations where it is not used (it can be done, but it is not simple and it would not be fast). So I want to implement something simpler, which will just draw an alarm signal if anyone tries to misuse this object, but keeps my object mutable.
The best solution I can think of is using a const-pointer-to-object (Obj * const) - this does not make the compiler complain, but I have my mutable object and a sort-of alarm signal -through the const - in place as well.
Does anyone have a better idea ?
I've traditionally seen these kind of scenarios implemented using a shared_ptr/weak_ptr combo. See here.
The owner/deleter would get a
boost::shared_ptr<T>
Your class would get a
boost::weak_ptr<T>
To reassign the weak ptr, simply reassign the pointer:
void MyClass::Reassign(boost::weak_ptr<T> tPtr)
{
m_tPtr = tPtr;
}
To use the weak ptr, first check to see if it's still around:
void MyClass::Use()
{
boost::shared_ptr<T> m_temporarySharedPtr = m_tPtr.lock();
if (m_temporarySharedPtr)
{
//...
}
}
The weak ptr can be made "NULL" by reseting it, or assigning it to an empty shared_ptr
void MyClass::MakeNull()
{
m_tPtr.reset();
}
You can make the destructor of that object private. That will trigger compile time error on attemp to delete object. Also you should allow restcted code to delete object by using friends mechanism or member function.
You can put a wrapper around the pointer to allow modification but not deletion:
template <typename T> class Wrapper
{
public:
Wrapper(T *p=0) : pointer(p) {}
T *operator->() {return pointer;}
T const *operator->() const {return pointer;}
operator bool() const {return pointer;}
private:
T *pointer;
};
You can use this just like a pointer to the template type in some contexts, but can't call delete on it. The wrapped type must be a struct or class type (i.e. a type where -> makes sense). Then one of your classes that uses, but doesn't manage the lifetime of, the object would look a bit like this:
class User
{
public:
void Assign(Object *o) {object = o;}
void UseObject() {if (object) object->Use();}
private:
Wrapper<Object> object;
};
Technically, you can still get at the raw pointer, but the code to do it is very wrong-looking:
delete wrapper.operator->();
Sounds like a case for a shared_ptr.
An alternative (if allowed by your restircitons) would be to create a dummy object similar to a shared pointer to act as a wrapper between the object in question and your classes.
Your classes can attempt to delete this object if they wish, but it itself will leave the original object untouched. Overload the * operator and you can use it transparently.
something like this?...
the Obj class is an aggregation of your new class, you point at it with an Obj* cont pObj, which you set up at the creation of your new class (or leave as 0 if it's not used), you then check pObj before calling any of its functions?
if ( pObj ){ pObj->foo(); }
if the function foo's incorrectly defined as mutable then you need to fix its declaration.
your new class isn't responsible for cleaning up/deleting the Obj class.