When do I need move-operations , c++ - c++

Imagine the following code
struct Vehicle { virtual void drive() = 0; };
struct Car: public Vehicle {
void drive() override { std::cout << "driving a car\r\n"; }
};
struct Cycle : public Vehicle {
void drive() override { std::cout << "driving a cycle\r\n"; }
};
Vehicle* makeVehicle(const std::string& type) {
if (type == "car") { return new Car(); }
else if (type == "cycle") { return new Cycle(); }
else { return nullptr; }
}
Do I need do implement moving-operations concerning "return new Car()"? Or are they senseless because of the use of pointers?
In which cases are the default moving-operation sufficient?
Cheers!

If you have move, you have C++11, and if you have C++11, you have unique_ptr. So you actually want to write your code like this:
std::unique_ptr<Vehicle> makeVehicle(const std::string& type {
if (type == "car") { return std::make_unique<Car>(); }
...
}
unique_ptr indicates that the person calling makeVehicle now owns the returned object and will automatically ensure that it gets destroyed and memory returned. unique_ptr implements move operations automatically, that's why this code can compile (if it wasn't movable or copyable, it wouldn't be possible to return it from a function).
So basically, for polymorphic types, typically you will not need to implement moving operations. But unique_ptr doesn't provide copying operations so you still may want to implement the oldie-but-goldie clone function (if you really need it).
I recommend reading more about move semantics and in particular the "Rule of Zero"; it's generally better to avoid implementing copy/move by hand where possible. See: http://en.cppreference.com/w/cpp/language/rule_of_three.

Related

Where should the objects created by a factory method be deleted?

How and where should the objects created by returnShapeType be deleted?
This is a factory method demonstration program.
Please show the code.
class Shape
{
public:
Shape() {}
virtual void print() {std::cout << "\nFrom shape print";}
};
class Triangle: public Shape
{
public:
Triangle(){}
virtual void print() {std::cout << "\nFrom triangle print";}
};
class Rectangle: public Shape
{
public:
Rectangle(){}
virtual void print() {std::cout << "\nFrom rect print";}
};
class CreateShapeObject
{
public:
CreateShapeObject() {}
Shape *returnShapeType( std::string arg )
{
if (arg == "Triangle")
return new Triangle;
else if (arg == "Rectangle")
return new Rectangle;
}
};
////////////
class EndDeveloper
{
public:
CreateShapeObject obj;
EndDeveloper()
{
Shape *p = obj.returnShapeType("Triangle");
p->print();
Shape *q = obj.returnShapeType("Rectangle");
q->print();
}
};
Using raw pointers is error prone. Use a unique_ptr:
std::unique_ptr<Shape> returnShapeType(const std::string& arg)
{
if (arg == "Triangle")
return std::make_unique<Triangle>();
else if (arg == "Rectangle")
return std::make_unique<Rectangle>();
throw std::invalid_argument("Invalid shape");
}
You can use it conveniently with auto:
auto shape = obj.returnShapeType("Triangle");
unique_ptr can be also implicitly converted to shared_ptr:
std::shared_ptr<Shape> shape = obj.returnShapeType("Triangle");
You have to establish ownership principles in your design.
In your posted code, CreateShapeObject does not retain a pointer to the object that was constructed. It simply returns a pointer to the constructed object. This implies the calling function/class must take ownership of the object. They ought to be responsible for deleting it unless they pass the ownership to another function/class in which case the other function/class ought to be responsible for deleting it.
If you want to make CreateShapeObject responsible for deleting the objects it constructs, you'll have to update it to keep track of the objects it constructs. At that point, you may want to change the name of the class to reflect the dual responsibility. Something along the lines of ShapeObjectManager will make more sense.
Treat any use of new via the factory like you would treat any other use of new.
I.e. the code/class which uses new (via factory or not) is responsible for doing the delete, too.

How to create a spy class against the clone idiom in C++

Coming from the Java/PHP world, I am still new to C++. Some simple things to do in other languages are a bit trickier to do in C++.
My main issue is the following. Right now, I have a class (ie. "Something") for which the constructor is injected with a virtual class dependency (ie. a children of "Base"). Then, the constructor stores this injected instance in a unique_ptr<Base> class field (using the clone idiom). This works well at the application level, everything seems to works as expected. Here is the sample code:
class Base {
public:
virtual std::unique_ptr<Base> clone() = 0;
virtual void sayHello() const = 0;
};
class Something {
public:
explicit Something(Base &base) { this->base = base.clone(); }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
But to make sure it does, I wrote unit tests to test its behavior. In those tests, I want to assert the injected dependencies methods are actually called. So logically, injecting a "spy" dependency should do the trick.
Here is what I did at first:
class SpyDerived : public Base {
public:
explicit SpyDerived() = default;
SpyDerived(const SpyDerived &original) { this->someState = original.someState; }
std::unique_ptr<Base> clone() override { return std::make_unique<SpyDerived>(*this); }
void sayHello() const override { std::cout << "My state: " << someState << std::endl; }
void setSomeState(bool value) { this->someState = value; }
private:
bool someState = false;
};
This is the main function I use to this this out:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
For obvious reasons, someState value on print is always false. I get that the Derived instances in Something is a new copy of Derived and no longer the one that was created in the main function.
So basically, what I am trying to achieve here is to have the Something class always use the SpyDerived instance created in the main function. Is there any way I could make this work. I am trying to avoid changing the design just for test purposes.
I am using MSVC 2015 to compile the code. Keep in mind that smart pointers, C++ idioms, copy/move constructors are fairly new concepts for me.
Thanks for your help.
Well, do you want to clone your instance, or simply reference that instance?
The clone idiom is made to copy the instance of a class, making the new instance independent of the old instance.
You are basically making this, in term of PHP:
<?php
interface Base {
public function sayHello();
}
class SpyDerived implements Base {
private $someState = false;
public function sayHello() {
echo 'My state: ' . $this->someState;
}
}
class Something {
public __construct(Base $base) { $this->base = clone $base; }
public function sayHello() { $this->base->sayHello(); }
private $base = null;
}
$derived = new SpyDerived;
$something = new Something($derived);
$derived->setSomeState(true);
$something->sayHello();
?>
You see this? $base is cloned. Something::$base is a copy.
So in PHP, what would you do to solve that problem?
Simple! Remove that clone, no copies!
Well, in C++, this is the same thing. If you have an object pointer and don't want to clone it, don't actually call the clone method.
We will change your class to, like PHP, contain a reference to the object. We will start by making Something contain a non owning reference:
class Something {
public:
explicit Something(Base& b) : base{b} { }
void sayHello() const { base.sayHello(); }
private:
// we simply contain a reference to the base
Base& base;
};
In C++, a reference does not own the object. If the object is destroyed, all reference pointing to that object will point to a dead object.
As you can notice, your tests stays the same and work:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
If you want Something be the owner of Base, then use std::unique_ptr<Base>:
class Something {
public:
explicit Something(std::unique_ptr<Base> b) : base{std::move(b)} { }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
Beware that the ownership of base should be transferred from the caller to the something class. That transfer is express through that std::move thing, because we are moving the ownership of that resource.
Then in your tests:
int main() {
auto derived = std::make_unique<SpyDerived>();
// We want to keep a non-owning reference of derived
// The star (*) operator of std::unique_ptr returns a reference to the pointed object
auto& derived_ref = *derived;
// We transfer the ownership of derived to the `Something`
Something something(std::move(derived));
// Since derived is a reference to the object pointed by our pointer,
// It will affect the value we found in `Something`, because they are
// both pointing to the same instance.
derived.setSomeState(true);
something.sayHello();
}
Since Something is owner of derived, the non-owning reference derived_ref will point to a dead object if something dies before.

Call derived class non virtual member functions from base class pointer

We know that, derived class members functions can be accessed through a base class pointer in C++ , provided that these member functions have to be virtual. Is there a means to access derived class member functions which are NOT virtual or pure virtual from base class pointer.
i.e. I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this?
For example, if I design a factory design pattern,
class Vehicle {
public:
virtual void printVehicle() = 0;
static Vehicle* Create(VehicleType type);
};
class TwoWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am two wheeler" << endl;
}
void Some2WheelerONLYSpecificOPeration()
{
}
};
class ThreeWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am three wheeler" << endl;
}
void Some3WheelerONLYSpecificOPeration()
{
}
};
class FourWheeler : public Vehicle {
public:
void printVehicle() {
cout << "I am four wheeler" << endl;
}
void Some4WheelerONLYSpecificOPeration()
{
}
};
// Factory method to create objects of different types.
// Change is required only in this function to create a new object type
Vehicle* Vehicle::Create(VehicleType type) {
if (type == VT_TwoWheeler)
return new TwoWheeler();
else if (type == VT_ThreeWheeler)
return new ThreeWheeler();
else if (type == VT_FourWheeler)
return new FourWheeler();
else return NULL;
}
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->Some2WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_ThreeWheeler);
basePtr->Some3WheelerONLYSpecificOPeration(); //HOW TO ACHIEVE THIS CALL
basePtr = Vehicle::Create(VT_FourWheeler);
basePtr->Some4WheelerONLYSpecificOPeration(); // //HOW TO ACHIEVE THIS CALL
}
I want to call derived class member functions which are present only in derived class & not in base class through base class pointer. How would I achieve this ?
You cannot call a non-virtual member function of the derived class with a pointer to the base class.
You'll need a pointer to the derived class. The simplest method is to use dynamic_cast to get a pointer to the derived class, check whether the cast was successful, then call the derived class member function using a derived class pointer.
A better method would be to provide a virtual member function in the base class and implement it in the derived class.
You can do what you want with dynamic_cast, but this will lead to disappointing results at a code review. Instead, I pitch you go the same route you did with printVehicle
class Vehicle
{
public:
// without a virtual destructor you are walking into
// a very bad bug. The wrong destructor may be called.
virtual ~Vehicle()
{
}
virtual void printVehicle() = 0;
// Specific stuff that all children must provide
virtual void doTypeSpecificStuff() = 0;
// this is actually a bit of a ideological weird. I'm not sure I can call
// it a flaw. By making this factory function a member of Vehicle, Vehicle
// must now know its children. If this is the case, the VehicleType enum
// should probably be a member of Vehicle, but personally I think this
// factory should be a totally free function.
static Vehicle* Create(VehicleType type);
};
class TwoWheeler: public Vehicle
{
public:
void printVehicle()
{
cout << "I am two wheeler" << endl;
}
void doTypeSpecificStuff()
{
cout << "Doing two wheeler stuff" << endl;
}
};
Leaving out the other two classes and Vehicle::Create to save space.
int main()
{
Vehicle* basePtr = Vehicle::Create(VT_TwoWheeler);
basePtr->doTypeSpecificStuff(); //HOW TO ACHIEVE THIS CALL
// leaking memory here, so
delete basePtr;
// but also look into std::unique_ptr. Much better suited to this behaviour
}
In fact, let's act on on that final comment about std::unique_ptr right now. A unique_ptr manages your dynamic allocations for you so you don't have to clutter up your code with deletes and run the risk of missing one or deleteing too soon. The unique_ptr's pointer is valid for as long as the unique_ptr is in scope. If you can compile, the pointer is good unless you done something silly like never point it at anything or manually remove the pointer.
And while we're at it, let's eliminate my earlier concerns about vehicle::Create.
First we define a free function to replace Create and return a unique_ptr. Since I hate to have to have if (ptr != NULL) checks all through my code to make sure an object really was created, let's also make a big stink about it when we can't match the provided vehicle type with class by throwing an exception.
And rather than a chain of if-else ifs we'll use a somewhat more elegant switch statement.
std::unique_ptr<Vehicle> SmarterVehicleFactory(VehicleType type)
{
switch (type)
{
case VT_TwoWheeler:
return std::make_unique<TwoWheeler>();
case VT_ThreeWheeler:
return std::make_unique<ThreeWheeler>();
case VT_FourWheeler:
return std::make_unique<FourWheeler>();
default:
throw std::runtime_error("Invalid Vehicle type");
}
}
And then we'll use this new function
int main()
{
try
{
std::unique_ptr<Vehicle> basePtr = SmarterVehicleFactory(VT_TwoWheeler);
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_ThreeWheeler);
// unique_ptr freed the TwoWheeler for us.
basePtr->doTypeSpecificStuff();
basePtr = SmarterVehicleFactory(VT_FourWheeler);
basePtr->doTypeSpecificStuff();
// just for laughs we will ask for a FiveWheeler, which we have not yet
// fully implemented
basePtr = SmarterVehicleFactory(VT_FiveWheeler); // will throw exception
basePtr->doTypeSpecificStuff(); // will not be executed
}
catch (const std::exception & exc)
{
cerr << "Rats! Something bad happened: " << exc.what();
// basePtr will be unmodified and still pointing to a FourWheeler
}
} // basePtr will go out of scope here and clean up our memory for us.
The beauty of this approach is no class knows anything about any other class. You can put Vehicle in a header with the SmarterVehicleFactory prototype and the list of vehicle types and hide everything else. The user sees nothing. Everybody is kept in the dark.
Why is that good? Because now you can change any of the above classes, except the Vehicle interface class, without having any effect on any of the other classes. This makes your code easier to maintain and debug.
I'm trying to find the best way to use polymorphism without using inheritance, because I want to avoid virtual calls. I was looking for a way to improve what I currently have (with no avail) and I stumbled on this question. This is the best I can do so far:
template<class VehicleDetails>
class Vehicle {
VehicleDetails details;
public:
VehicleDetails& getDetails() {
return details;
}
const VehicleDetails& getDetails() const {
return details;
}
void printDetails() const {
details.printDetails();
}
}
class TwoWheeler {
public:
void printDetails() const {
cout << "I am two wheeler" << endl;
}
void specificTwoWheelerMethod() const {
cout << "I am specific functionality" << endl;
}
}
Then you use it as such:
Vehicle<TwoWheeler> vehicle;
vehicle.printDetails(); // prints "I am two wheeler"
Unfortunately this complicates things. Now every class/struct or function that takes a vehicle must be templated, unless you know the type of vehicle.
template<class VehicleDetails>
void doGeneralVehicleThings(const Vehicle<VehicleDetails>& vehicle) {
// ...
}
On the plus side when you do know the type you can access specific functionality via the getDetails() method without any casting or runtime overhead involved:
void doTwoWheelerThings(const Vehicle<TwoWheeler>& twoWheelerVehicle) {
twoWheelerVehicle.getDetails().specificTwoWheelerMethod(); // prints "I am specific functionality"
}

Change the class of an object: possible with std::move?

I know that I cannot mess with the V-Table (in a somewhat sane way) once an object is created. Which means I have to copy an object to change it's type. Does this also hold true with c++11's std::move and friends?
class Base {
public:
virtual int type() = 0;
// more data members I want to avoid to copy
};
class D1 : public Base {
public:
int type() {
return 1;
}
};
class D2 : public D1 {
public:
int type() {
return 2;
}
};
int main()
{
// creating the actual object, type is D1
D1* obj = new D1();
// this is what does not work, I want to "change" the object to D2
D2* obj2 = &std::move<D2>(*obj);
// cast it to obj2 base class
Base* baseObj = static_cast<D1*>(obj2);
// now I want a "2" here
int t = baseObj->type();
printf ("%d\n", t);
}
I do not know the move semantics very well... But is there something I can change a D1 object into D2 (or vice versa) with type safety? (Both classes are virtually the same from the memory layout)
While you cannot change the type of an existing object, you can easily change the dynamic type of a pointer member and achieve the desired effect. This is known as strategy design pattern.
E.g.:
#include <memory>
#include <iostream>
class Host
{
struct Strategy
{
virtual ~Strategy() = default;
virtual int type() const = 0;
};
struct StrategyA : Strategy { int type() const override { return 1; } };
struct StrategyB : Strategy { int type() const override { return 2; } };
std::unique_ptr<Strategy> strategy_;
public:
Host()
: strategy_(new StrategyA)
{}
int type() const { return strategy_->type(); }
void change_strategy(int type) {
switch(type) {
case 1: strategy_.reset(new StrategyA); break;
case 2: strategy_.reset(new StrategyB); break;
default: std::abort();
}
}
};
int main() {
Host host;
std::cout << host.type() << '\n';
host.change_strategy(2);
std::cout << host.type() << '\n';
}
It seems to me you are not familiar with what std::move actually does.
As others have said, std::move doesn't actually move anything. It obtains an xvalue (a variable that has a name, but can have its resources reused or transfered to another object) reference from an lvalue (essentially a named variable), so, std::move is nothing but a cast. It doesn't create any new object. Read more about it here and here.
Still about move semantics topic,
std::move is mostly useful so that you can force rvalue-aware methods to receive and reuse resources in variables that you absolutely know that can have their resources moved.
To get a more indepth insight of this, I'd recommend reading What are move semantics?. For instance, one of its uses is creating an object from a temporary (e.g, objects created inside a function and then returned):
#include <vector>
#include <iostream>
class A {
public:
// A very large resource
std::vector<int> resource;
// Constructs our very large resource
A(): resource(1024, 0) { std::cout << "Default construct" << std::endl; }
// Move (reuses) a very large resource from an instance
A(A && other) : resource(std::move(other.resource)) {
std::cout << "Move construct" << std::endl;
}
};
Now, A's move constructor is only called when the other object is an rvalue (or an xvalue), such as:
A foo(A a) { return a; }
int main() {
A a = foo(A());
return 0
}
In this scenario, before foo() gets called, a temporary A() is created and passed in as argument. foo() returns it, but since it is a temporary , it fits as an rvalue and is passed to the move constructor of A when constructing A a = foo(A()).
Inside the move constructor of A(), std::move(other.resource) is used when constructing another resource to call the move constructor of std::vector so that it can try to use whatever it can from other.resource instead of creating everything from scratch again (and then copying).
But as stated previously, std::move on itself doesn't move anything, but it is there to convey intent to move, help the compiler do the right thing (and other programmers to read it and understand faster what you meant).
So, to answer your question directly, no, there isn't anything that'd let you transform an object into another, other than constructing a new object. If you are sure that you are going to destroy obj (which you are not doing, by the way), you can implement an constructor of D2 that accepts an rvalue of D1:
class D2 {
public:
D2(D1 && d1) : resource(std::move(d1.resource)) { d1.resource = nullptr; }
}
int main() {
D1 * obj = new D1();
D2 * obj2 = new D2(std::move(*obj));
delete obj;
}
There are other things to consider when doing this, though, such as destructors of moved objects and other details. I'd recommend reading more about the subject and also maybe using a different method of achieving what you are doing, such as the Strategy pattern mentioned in another answer.

How to limit to stack allocations for polymorphic solution of resolving types [duplicate]

How do I allocate a polymorphic object on the stack? I'm trying to do something similar to (trying to avoid heap allocation with new)?:
A* a = NULL;
switch (some_var)
{
case 1:
a = A();
break;
case 2:
a = B(); // B is derived from A
break;
default:
a = C(); // C is derived from A
break;
}
You can't structure a single function to work like that, since automatic or temporary objects created inside a conditional block can't have their lifetimes extended into the containing block.
I'd suggest refactoring the polymorphic behaviour into a separate function:
void do_something(A&&);
switch (some_var)
{
case 1:
do_something(A());
break;
case 2:
do_something(B()); // B is derived from A
break;
default:
do_something(C()); // C is derived from A
break;
}
Disclaimer: I definitely don't think this is a good solution. The good solutions are to either rethink the design (maybe OO polymorphism is not warranted here given that there is a bounded number of possibilities?), or to use a second function to pass along said polymorphic object by reference.
But since other folks mentioned this idea, but got details wrong, I'm posting this answer to show how to get it right. Hopefully I get it right.
It is clear the the number of possible types is bounded. This means that a discriminated union, like boost::variant could solve the problem, even if it's not pretty:
boost::variant<A, B, C> thingy =
some_var == 1? static_cast<A&&>(A())
: some_var == 2? static_cast<A&&>(B())
: static_cast<A&&>(C());
The fact that now you can use things like static visitors is one if the things that keeps making me think this isn't a good use of OO polymorphism.
If instead of a ready-made solution, you want to use placement new by hand as suggested in other answers, there are a number of things that need care because we lose some of the properties of regular automatic objects in the process:
the compiler no longer gives us the right size and alignment;
we no longer get an automatic call to the destructors;
In C++11, these are both easy to fix with aligned_union and unique_ptr, respectively.
std::aligned_union<A, B, C>::type thingy;
A* ptr;
switch (some_var)
{
case 1:
ptr = ::new(&thingy.a) A();
break;
case 2:
ptr = ::new(&thingy.b) B();
break;
default:
ptr = ::new(&thingy.c) C();
break;
}
std::unique_ptr<A, void(*)(A*)> guard { ptr, [](A* a) { a->~A(); } };
// all this mechanism is a great candidate for encapsulation in a class of its own
// but boost::variant already exists, so...
For compilers that don't support these features, you can get alternatives: Boost includes aligned_storage and alignment_of traits which can be used to build aligned_union; and unique_ptr can be replaced with some kind of scope guard class.
Now that that is out of the way, just so it's clear, don't do this and simply pass a temporary along to another function, or revisit the design altogether.
If B is your base types D1, D2, and D3 are your derived types:
void foo()
{
D1 derived_object1;
D2 derived_object2;
D3 derived_object3;
B *base_pointer;
switch (some_var)
{
case 1: base_pointer = &derived_object1; break;
....
}
}
If you want to avoid wasting the space of the three derived objects, you could break up your method into two parts; the part that chooses which type you need, and the part of the method that works on it. Having decided which type you need, you call a method that allocates that object, creates a pointer to it, and calls the second half of the method to complete the work on the stack-allocated object.
I wrote a generic template to do it. Full code available here (it became too elaborate for the scope of this question).
StackVariant object contains a buffer of the size of the biggest type out of the provided types, and biggest alignment as well. The Object is constructed on the stack using a 'placement new' and operator->() is used for polymorphic access to suggest the indirection. Also, it is important to make sure that if a virtual detor is defined, it should be called upon destruction of the object on the stack, so the template detor is doing just that using a SFINAE definition.
(see usage example and output below):
// compile: g++ file.cpp -std=c++11
#include <type_traits>
#include <cstddef>
// union_size()/union_align() implementation in gist link above
template<class Tbaseclass, typename...classes>
class StackVariant {
alignas(union_align<classes...>()) char storage[union_size<classes...>()];
public:
inline Tbaseclass* operator->() { return ((Tbaseclass*)storage); }
template<class C, typename...TCtor_params>
StackVariant& init(TCtor_params&&...fargs)
{
new (storage) C(std::forward<TCtor_params>(fargs)...); // "placement new"
return *this;
};
template<class X=Tbaseclass>
typename std::enable_if<std::has_virtual_destructor<X>::value, void>::type
call_dtor(){
((X*)storage)->~X();
}
template<class X=Tbaseclass>
typename std::enable_if<!std::has_virtual_destructor<X>::value, void>::type
call_dtor() {};
~StackVariant() {
call_dtor();
}
};
Usage example:
#include <cstring>
#include <iostream>
#include "StackVariant.h"
class Animal{
public:
virtual void makeSound() = 0;
virtual std::string name() = 0;
virtual ~Animal() = default;
};
class Dog : public Animal{
public:
void makeSound() final { std::cout << "woff" << std::endl; };
std::string name() final { return "dog"; };
Dog(){};
~Dog() {std::cout << "woff bye!" << std::endl;}
};
class Cat : public Animal{
std::string catname;
public:
Cat() : catname("gonzo") {};
Cat(const std::string& _name) : catname(_name) {};
void makeSound() final { std::cout << "meow" << std::endl; };
std::string name() final { return catname; };
};
using StackAnimal = StackVariant<Animal, Dog, Cat>;
int main() {
StackAnimal a1;
StackAnimal a2;
a1.init<Cat>("gonzo2");
a2.init<Dog>();
a1->makeSound();
a2->makeSound();
return 0;
}
// Output:
// meow
// woff
// woff bye!
Few things to note:
I wrote it while trying to avoid heap allocations in performance critical functions and it did the job - 50% speed gains.
I wrote it to utilize C++'s own polymorphic mechanisms. Before that my code was full of switch-cases like the previous suggestions here.
You can't create a polymorphic local variable
You can't create a polymorphic local variable, since a subclass B of A might have more attributes than A, thus take more place, so the compiler would have to reserve enough space for the largest subclass of A.
In case you have dozens of subclasses, and one of them has a large number of attributes, this would waste a lot of space.
In case you put in the local variable an instance of a subclass of A you received as a parameter, and you put your code in a dynamic library, then the code linking with it could declare a subclass larger than those in your library, so the compiler wouldn't have allocated enough space on the stack anyway.
So allocate space for it yourself
Using placement new, you can initialize the object in a space you allocated through some other means:
alloca, but seeing this SO question it seems it's not the best option.
A Variable Length Array, with which comes some (non-)portability fun, since it works under GCC but isn't in the C++ standard (not even in C++11)
aligned_union<A, B, C>::type, as suggested by R. Martinho Fernandes in a comment to this answer
However, these techniques may use a lot of extra space, and don't work if you are given a reference (pointer) to an unknown-at-compile-time subclass of A that is larger than the types you accounted for.
The solution I propose is to have a kind of factory method on each subclass, that calls a supplied function with a pointer to a stack-allocated instance of the given subclass. I added an extra void* parameter to the supplied function's signature, so one can pass it arbitrary data.
#MooingDuck suggested this implementation using templates and C++11 in a comment below. In case you need this for code that can't benefit from C++11 features, or for some plain C code with structs instead of classes (if struct B has a first field of type struct A, then it can be manipulated somewhat like a "substruct" of A), then my version below will do the trick (but without being type-safe).
This version works with newly defined subclasses, as long as they implement the ugly factory-like method, and it will use a constant amount of stack for the return address and other informations required by this intermediate function, plus the size of an instance of the requested class, but not the size of the largest subclass (unless you choose to use that one).
#include <iostream>
class A {
public:
int fieldA;
static void* ugly(void* (*f)(A*, void*), void* param) {
A instance;
return f(&instance, param);
}
// ...
};
class B : public A {
public:
int fieldB;
static void* ugly(void* (*f)(A*, void*), void* param) {
B instance;
return f(&instance, param);
}
// ...
};
class C : public B {
public:
int fieldC;
static void* ugly(void* (*f)(A*, void*), void* param) {
C instance;
return f(&instance, param);
}
// ...
};
void* doWork(A* abc, void* param) {
abc->fieldA = (int)param;
if ((int)param == 4) {
((C*)abc)->fieldC++;
}
return (void*)abc->fieldA;
}
void* otherWork(A* abc, void* param) {
// Do something with abc
return (void*)(((int)param)/2);
}
int main() {
std::cout << (int)A::ugly(doWork, (void*)3);
std::cout << (int)B::ugly(doWork, (void*)1);
std::cout << (int)C::ugly(doWork, (void*)4);
std::cout << (int)A::ugly(otherWork, (void*)2);
std::cout << (int)C::ugly(otherWork, (void*)11);
std::cout << (int)B::ugly(otherWork, (void*)19);
std::cout << std::endl;
return 0;
}
By then, I think we might have outweighed the costs of a simple malloc, so you might wand to use that after all.
You can do it with placement new. This will place the items on the stack, in the memory contained in the buffer. However, these variables are not automatic. The downside is that your destructors won't run automatically, you would need to properly destruct them just as you've created them when they go out of scope.
A reasonable alternative to manually calling the destructor is to wrap your type in a smart pointer, as shown below:
class A
{
public:
virtual ~A() {}
};
class B : public A {};
class C : public B {};
template<class T>
class JustDestruct
{
public:
void operator()(const T* a)
{
a->T::~T();
}
};
void create(int x)
{
char buff[1024] // ensure that this is large enough to hold your "biggest" object
std::unique_ptr<A, JustDestruct<T>> t(buff);
switch(x)
{
case 0:
ptr = new (buff) A();
break;
case 1:
ptr = new (buff) B();
break;
case 2:
ptr = new (buff) C();
break;
}
// do polymorphic stuff
}
Polymorphism doesn't work with values, you need a reference or a pointer. You can use a const reference to a temporary object polymorphically and it will have the lifetime of a stack object.
const A& = (use_b ? B() : A());
If you need to modify the object, you have no choice but to dynamically allocate it (unless you're using Microsoft's non-standard extension that lets you bind a temporary object to a non-const reference).
A combination of a char array and placement new would work.
char buf[<size big enough to hold largest derived type>];
A *a = NULL;
switch (some_var)
{
case 1:
a = new(buf) A;
break;
case 2:
a = new(buf) B;
break;
default:
a = new(buf) C;
break;
}
// do stuff with a
a->~A(); // must call destructor explicitly
To strictly answer your question - what you have now does just that - i.e. a = A(); and a = B() and a = C(), but these objects are sliced.
To achieve polymorphic behavior with the code you have, I', afraid that's not possible. The compiler needs to know the size beforehand of the object. Unless you have references or pointers.
If you use a pointer, you need to make sure it doesn't end up dangling:
A* a = NULL;
switch (some_var)
{
case 1:
A obj;
a = &obj;
break;
}
won't work because obj goes out of scope. So you're left with:
A* a = NULL;
A obj1;
B obj2;
C obj3;
switch (some_var)
{
case 1:
a = &obj1;
break;
case 2:
a = &obj2;
break;
case 3:
a = &obj3;
break;
}
This of course is wasteful.
For references it's a bit trickier because they have to be assigned on creation, and you can't use temporaries (unless it's a const reference). So you'll probably need a factory that returns a persistent reference.
trying to avoid heap allocation with new)?
Well in that case you create object on stack as usual and assign address to the base pointer. But remember, if this is done inside a function, don't pass the address as return value, because stack will unwind after the function call returns.
So this is bad.
A* SomeMethod()
{
B b;
A* a = &b; // B inherits from A
return a;
}
It is possible, but it's a lot of effort to do cleanly (without manual placement new and exposed raw buffers, that is).
You're looking at something like Boost.Variant, modified to restrict the types to a base class and some derived classes, and to expose a polymorphic reference to the base type.
This thing (PolymorphicVariant ?) would wrap all the placement new stuff for you (and also take care of safe destruction).
If it's really what you want, let me know and I'll give you a start. Unless you really need exactly this behaviour though, Mike Seymour's suggestion is more practical.
Run this short program and you'll see why polymorphic objects do not work on the stack very well. When you create a stack object of a derived type that is unknown and expect it to be returned from a function call, what happens is the object is destroyed when that calling function goes out of scope. Thus the object only lives as long as that function is within scope. In order to return a valid object that will outlive the calling function you need to use the heap. This is demonstrated with this simple hierarchy and two versions of the same function with a switch statement except one does the stack and the other does it on the heap. Look at the output from both implementations and look to see what methods are called, what class they are being called from and when they are being called.
#include <string>
#include <iostream>
class Base {
public:
enum Type {
DERIVED_A = 0,
DERIVED_B,
DERIVED_C
};
protected:
Type type_;
public:
explicit Base(Type type) : type_(type) {
std::cout << "Base Constructor Called." << std::endl;
}
virtual ~Base() {
std::cout << "Base Destructor Called." << std::endl;
}
virtual void doSomething() {
std::cout << "This should be overridden by derived class without making this a purely virtual method." << std::endl;
}
Type getType() const { return type_; }
};
class DerivedA : public Base {
public:
DerivedA() : Base(DERIVED_A) {
std::cout << "DerivedA Constructor Called." << std::endl;
}
virtual ~DerivedA() {
std::cout << "DerivedA Destructor Called." << std::endl;
}
void doSomething() override {
std::cout << "DerivedA overridden this function." << std::endl;
}
};
class DerivedB : public Base {
public:
DerivedB() : Base(DERIVED_B) {
std::cout << "DerivedB Constructor Called." << std::endl;
}
virtual ~DerivedB() {
std::cout << "DerivedB Destructor Called." << std::endl;
}
void doSomething() override {
std::cout << "DerivedB overridden this function." << std::endl;
}
};
class DerivedC : public Base {
public:
DerivedC() : Base(DERIVED_C) {
std::cout << "DerivedC Constructor Called." << std::endl;
}
virtual ~DerivedC() {
std::cout << "DerivedC Destructor Called." << std::endl;
}
void doSomething() override {
std::cout << "DerivedC overridden this function." << std::endl;
}
};
Base* someFuncOnStack(Base::Type type) {
Base* pBase = nullptr;
switch (type) {
case Base::DERIVED_A: {
DerivedA a;
pBase = dynamic_cast<Base*>(&a);
break;
}
case Base::DERIVED_B: {
DerivedB b;
pBase = dynamic_cast<Base*>(&b);
break;
}
case Base::DERIVED_C: {
DerivedC c;
pBase = dynamic_cast<Base*>(&c);
break;
}
default: {
pBase = nullptr;
break;
}
}
return pBase;
}
Base* someFuncOnHeap(Base::Type type) {
Base* pBase = nullptr;
switch (type) {
case Base::DERIVED_A: {
DerivedA* pA = new DerivedA();
pBase = dynamic_cast<Base*>(pA);
break;
}
case Base::DERIVED_B: {
DerivedB* pB = new DerivedB();
pBase = dynamic_cast<Base*>(pB);
break;
}
case Base::DERIVED_C: {
DerivedC* pC = new DerivedC();
pBase = dynamic_cast<Base*>(pC);
break;
}
default: {
pBase = nullptr;
break;
}
}
return pBase;
}
int main() {
// Function With Stack Behavior
std::cout << "Stack Version:\n";
Base* pBase = nullptr;
pBase = someFuncOnStack(Base::DERIVED_B);
// Since the above function went out of scope the classes are on the stack
pBase->doSomething(); // Still Calls Base Class's doSomething
// If you need these classes to outlive the function from which they are in
// you will need to use heap allocation.
// Reset Base*
pBase = nullptr;
// Function With Heap Behavior
std::cout << "\nHeap Version:\n";
pBase = someFuncOnHeap(Base::DERIVED_C);
pBase->doSomething();
// Don't Forget to Delete this pointer
delete pBase;
pBase = nullptr;
char c;
std::cout << "\nPress any key to quit.\n";
std::cin >> c;
return 0;
}
Output:
Stack Version:
Base Constructor Called.
DerivedB Constructor Called.
DerivedB Destructor Called.
Base Destructor Called.
This should be overridden by derived class without making this a purely virtual method.
Heap Version:
Base Constructor Called.
DerivedC Constructor Called.
DerivedC overridden this function.
DerivedC Destructor called.
Base Destructor Called.
I'm not saying that it can not be done; I'm just stating the caveats in trying to do so. It may be ill-advised to try to do something of the sort. I do not know of any way to do this unless if you have a wrapper class that will contain the stack allocated objects to manage their life time. I'll have to try and work on that to see if I can come up with something of the sort.