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.
Related
I have a tricky situation. Its simplified form is something like this
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
And then in one class I do something like...
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
And in yet another class...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
And they share this Instruction vector somehow. My concern is the part where I do "execute" function. Will it work? Will it retain its Add type?
No, it won't.
vector<Instruction> ins;
stores values, not references. This means that no matter how you but that Instruction object in there, it'll be copied at some point in the future.
Furthermore, since you're allocating with new, the above code leaks that object. If you want to do this properly, you'll have to do
vector<Instruction*> ins
Or, better yet:
vector< std::reference_wrapper<Instruction> > ins
I like this this blog post to explain reference_wrapper
This behavior is called object slicing.
So you will need some kind of pointer. A std::shared_ptr works well:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Keep in mind that PInstruction is reference-counted, so that the copy constructor of PInstruction will create a new "reference" to the same object.
If you want to make a copy of the referenced object you will have to implement a clone method:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
If performance is an issue than you can look at std::unique_ptr, this is a little trickier to manage as move semantics are always required, but it avoids the cost of some atomic operations.
You can also use raw pointers and manage the memory manually with some sort of memory pool architecture.
The underlying problem is that to have a polymorphic type the compiler doesn't know how big the subclasses are going to be, so you can't just have a vector of the base type, as it won't have the extra space needed by subclasses. For this reason you will need to use pass-by-reference semantics as described above. This stores a pointer to the object in the vector and then stores the object on the heap in blocks of different sizes depending on what the subclass needs.
No, that will not work; you are "slicing" the Add object, and only inserting its Instruction part into the array. I would recommend that you make the base class abstract (e.g. by making execute pure virtual), so that slicing gives a compile error rather than unexpected behaviour.
To get polymorphic behaviour, the vector needs to contain pointers to the base class.
You will then need to be careful how you manage the objects themselves, since they are no longer contained in the vector. Smart pointers may be useful for this; and since you're likely to be dynamically allocating these objects, you should also give the base class a virtual destructor to make sure you can delete them correctly.
You may want to do a couple things, A: change the type of "v" to "vector", B: managed your memory with the "delete" operator. To answer your question, with this approach, yes, but you will only be able to access the interface from "Instruction", if you KNOW the type of something an "Instruction" pointer is pointing to I would suggest using dynamic_cast if you need to access the interface from, say, "Add".
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.
I have a tricky situation. Its simplified form is something like this
class Instruction
{
public:
virtual void execute() { }
};
class Add: public Instruction
{
private:
int a;
int b;
int c;
public:
Add(int x, int y, int z) {a=x;b=y;c=z;}
void execute() { a = b + c; }
};
And then in one class I do something like...
void some_method()
{
vector<Instruction> v;
Instruction* i = new Add(1,2,3)
v.push_back(*i);
}
And in yet another class...
void some_other_method()
{
Instruction ins = v.back();
ins.execute();
}
And they share this Instruction vector somehow. My concern is the part where I do "execute" function. Will it work? Will it retain its Add type?
No, it won't.
vector<Instruction> ins;
stores values, not references. This means that no matter how you but that Instruction object in there, it'll be copied at some point in the future.
Furthermore, since you're allocating with new, the above code leaks that object. If you want to do this properly, you'll have to do
vector<Instruction*> ins
Or, better yet:
vector< std::reference_wrapper<Instruction> > ins
I like this this blog post to explain reference_wrapper
This behavior is called object slicing.
So you will need some kind of pointer. A std::shared_ptr works well:
typedef shared_ptr<Instruction> PInstruction;
vector<PInstruction> v;
v.emplace_back(make_shared<Add>());
PInstruction i = v[0];
Keep in mind that PInstruction is reference-counted, so that the copy constructor of PInstruction will create a new "reference" to the same object.
If you want to make a copy of the referenced object you will have to implement a clone method:
struct Instruction
{
virtual PInstruction clone() = 0;
...
}
struct Add
{
PInstruction clone() { return make_shared<Add>(*this); }
...
}
PInstruction x = ...;
PInstruction y = x->clone();
If performance is an issue than you can look at std::unique_ptr, this is a little trickier to manage as move semantics are always required, but it avoids the cost of some atomic operations.
You can also use raw pointers and manage the memory manually with some sort of memory pool architecture.
The underlying problem is that to have a polymorphic type the compiler doesn't know how big the subclasses are going to be, so you can't just have a vector of the base type, as it won't have the extra space needed by subclasses. For this reason you will need to use pass-by-reference semantics as described above. This stores a pointer to the object in the vector and then stores the object on the heap in blocks of different sizes depending on what the subclass needs.
No, that will not work; you are "slicing" the Add object, and only inserting its Instruction part into the array. I would recommend that you make the base class abstract (e.g. by making execute pure virtual), so that slicing gives a compile error rather than unexpected behaviour.
To get polymorphic behaviour, the vector needs to contain pointers to the base class.
You will then need to be careful how you manage the objects themselves, since they are no longer contained in the vector. Smart pointers may be useful for this; and since you're likely to be dynamically allocating these objects, you should also give the base class a virtual destructor to make sure you can delete them correctly.
You may want to do a couple things, A: change the type of "v" to "vector", B: managed your memory with the "delete" operator. To answer your question, with this approach, yes, but you will only be able to access the interface from "Instruction", if you KNOW the type of something an "Instruction" pointer is pointing to I would suggest using dynamic_cast if you need to access the interface from, say, "Add".
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.
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".