Virtual functions and vectors(C++) [duplicate] - c++

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".

Related

Conditional declaration of objects inherting from a common base class to pass a reference to one of them

Say I have two classes inheriting from a common base, such as
class Thing{
public:
virtual void f()=0;
};
class Thing_variant_a: public Thing{
public:
void f(){
std::cout<<"I am (a)"<<std::endl;
}
};
class Thing_variant_b: public Thing{
public:
void f(){
std::cout<<"I am (b)"<<std::endl;
}
};
And a function taking a reference to a Thing object as an argument.
void function(Thing& t){
t.f();
}
Depending on conditions I would like to call function with either a thing_a or thing_b (and possibly extend this at some point adding another possibility of thing_c)
I know I can do this using a pointer
Thing *t = nullptr;
if(condition_a){
t = new Thing_variant_a();
} else if(condition_b){
t = new Thing_variant_b();
}
function(*t);
However, I would like to know if there is a better way, that
does not allocate heap memory
does not require me to take care of deleting t at some point (probably smart pointers, but I don't know much about those)
ensures I always pass a valid Thing reference to function (there might be more conditionals in a complicated structure than in this minimal example) I could do if(t){ function(*t);}else{/*handle error*/}), but it seems like there should be a more elegant solution.
If not all of the above are possible any combination of those?
This sounds very much like an XY problem. There is probably a different solution to your problem entirely.
C++ is a statically-typed language; that means types used in a given code path are fixed at compile-time. Dynamic types (types known at run time) are normally allocated via the heap or all-at-once and then selected at run time.
So not much is possible in your case as you've noticed..
You could for example just have two different code paths:
if (condition_a) {
Thing_variant_a a;
function(a);
} else if (condition_b) {
Thing_variant_a b;
function(b);
}
Preallocate the types:
Thing_variant_a a;
Thing_variant_a b;
if (condition_a) {
function(a);
} else if (condition_b) {
function(b);
}
Or use a template:
template<typename T>
void do_something() {
T t;
function(t);
}
// somewhere else in the code ...
do_something<Thing_variant_a>();
// or ...
do_something<Thing_variant_b>();
Here's a way using dynamic memory and unique_ptr:
std::unique_ptr<Thing> t;
if (condition_a) {
t = std::make_unique<Thing_variant_a>();
} else if (condition_b) {
t = std::make_unique<Thing_variant_b>();
}
function(*t);
// t is delete'd automatically at end of scope...
And by the way, a function like int f(){...} should return some int value.
Here is a way to do it without using the heap or pointers:
Thing_variant_a thingA;
Thing_variant_b thingB;
if(condition_a){
function(thingA);
} else if(condition_b){
function(thingB);
}
If you want, you reduce it to a single call via the ternary operator:
Thing_variant_a thingA;
Thing_variant_b thingB;
function(condition_a ? static_cast<Thing &>(thingA) : static_cast<Thing &>(thingB));
As far as references go, references in C++ are required to be always be non-NULL -- so if you try to dereference a NULL pointer (e.g. by calling function(*t) when t==NULL) you've already invoked undefined behavior and are doomed; there is nothing the code inside function() can do to save you. So if there is any change that your pointer is NULL, you must check for that before dereferencing it.
I'll try to answer each of your questions
does not allocate heap memory
Unfortunately c++ only supports polymorphism using pointers. I guess the problem you would face here is fragmented memory (meaning that your pointers are everywhere in the heap). The best way to handle that is to allocate the memory using a memory pool.
You could use an std::variant but you will still need to test for the currently available type in the variant.
does not require me to take care of deleting t at some point (probably smart pointers, but I don't know much about those)
You could use a std::unique_ptr which will basically called the destructor when no one holds that pointer anymore.
ensures I always pass a valid Thing reference to function (there might be more conditionals in a complicated structure than in this minimal example) I could do if(t){ function(*t);}else{/handle error/}), but it seems like there should be a more elegant solution.
If you use pointers your could just check for the nullptr as you are doing right now. I'm not sure what you are meaning by valid reference as a reference always points toward something and cannot be empty.

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.

Storing an inherited class in a vector [duplicate]

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".

Efficient factory functions without pointers (including smart pointers) or copies?

Suppose I have some kind of factory function which creates objects that are largely used for a very short timespan only (possibly just for the duration of the scope of the function where this factory function is called).
Like this:
foo factory(some_parameter fancy_parameter)
{
return foo(fancy_parameter);
}
//this gets called all the time... very often
void every_frame_function()
{
for(int i=0; i<big_number; ++i)
do_something_with(factory(some_parameter(i));
} //don't need those foos out here!
Is there a way to implement such factories without having the user care about memory management (by returning a pointer), without having to deal with smartpointer overhead and without returning a foo object that has to be hardcopied?
Maybe I'm asking for a goose that lays golden eggs here, but maybe there are some move semantics to be used here (I just don't know how).
Use std::unique_ptr<T>, it has zero overhead compared with a raw pointer.
Or simply return by value, but then you cannot do subtype polymorphism.
The compiler will in many cases optimize out the copy, depending on what you do with it. For example:
type create();
void test {
type local = create(); // Copy will be elided
type const & ref = create(); // Extra copy will be elided
local = create();
}
This is assuming that create is implemented in a way that (N)RVO can be applied, or else there would be another internal copy before returning from create.
Now, what is interesting is determining whether this is the correct approach or not which we cannot do since you are not providing enough information about the problem. For example, how costly are the objects returned by the factory to create, whether they hold resources, or whether you could reuse the object...
I think that's a problem about the deep copy and the shallow copy. Pointers are similar to a shallow copy.
Details for the two copies: http://en.wikipedia.org/wiki/Object_copy#In_C.2B.2B
Without using pointers in another function, you have to use the deep copy in your code. If the object is very big, deep copy will cost a lot of time, cause the program very slow. In your example about 2-dimensional vectors, the difference between the two copies is not obvious. But if the object is as large as a complicated dialog, the effect is very clear.
Well, you can't do it with a factory function, but you can do it with a class:
class Factory {
public:
Base &create_obj(some_param p)
{
d.p =p;
return d;
}
private:
Derived d;
};
void every_frame_function() {
Factory f;
for(int i=0;i<bignumber;i++)
{
do_something_with(f.create_obj(some_parameter(i)));
}
}

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".