Static members being destroyed while there are still outstanding instances? - c++

I need to access a static data member from a destructor, but on program exit it seems that it cannot be guaranteed to still exist! For some reason, the static members are being destroyed whilst there are still outstanding instances of the class. It's odd because I've never heard the advice "Never access static members from a destructor" before, and yet I think I'd know about such a limitation if it existed.
I'll give a concrete example:
class MyClass {
public:
~MyClass() { m_instances.erase(m_name); }
private:
long m_name;
static std::map<long, MyClass*> m_instances;
};
In another class, I tried the following nasty hack which appeared to work, though when I think about it I don't think it's really a solution at all.
class MyClass {
friend class Switch;
public:
~MyClass() { if (m_alive) m_instances.erase(m_name); }
private:
static bool m_alive;
class Switch {
~Switch() { MyClass::m_alive = false; }
};
static Switch m_switch;
long m_name;
static std::map<long, MyClass*> m_instances;
};
What if an instance of MyClass is destroyed after m_instances but before m_switch?? And even if m_switch dies first, the boolean m_alive might have been "destroyed" and therefore possibly overwritten to 'true' (unlikely, I know).
So can anyone offer a better solution? I expect I am missing something very obvious here.

This is clearly a problem of static destruction order. I would recommend something like the following:
class MyClass {
public:
MyClass() { add_instance(m_name, this); };
~MyClass() { erase_instance(m_name); }
private:
long m_name;
static std::map<long, MyClass*>& get_instance_map();
static void add_instance(long aName, MyClass* aObj);
static void erase_instance(long aName);
};
std::map<long, MyClass*>* MyClass::get_instance_map() {
static std::map<long, MyClass*>* p_inst = new std::map<long, MyClass*>();
return p_inst;
};
void MyClass::add_instance(long aName, MyClass* aObj) {
static std::map<long, MyClass*>* p_inst = MyClass::get_instance_map();
p_inst->insert( std::make_pair(aName, aObj) );
};
void MyClass::erase_instance(long aName) {
static std::map<long, MyClass*>* p_inst = MyClass::get_instance_map();
p_inst->erase( aName );
};
If you need the instance map to be deleted, it might not be possible. Otherwise, just use a normal construct-on-first-use idiom. The point here is that the map is a heap-allocated std::map object, and not deleting it just means that it will be flushed away as the OS reclaims the freestore memory which will occur after every other "normal" execution, like a destructor call.

There is no guarantee that static members are destroyed only after all instances of an object of the same class. C++ incorporates no reference counting paradigm (shared_ptr notwithstanding).
When considering lifetime, consider your static members as any other static object. There's really nothing binding them to their containing class other than being in the class's "namespace" (warning: not accurate terminology).
So, if your myClass instances are created statically too, then you need to consider normal static object lifetime rules between them:
Example #1:
#include <iostream>
struct A {
A() { std::cout << "*A "; };
~A() { std::cout << "~A "; };
};
struct B {
B() { std::cout << "*B "; };
~B() { std::cout << "~B "; };
static A a;
};
B t;
A B::a;
int main() {}
// Output: *B *A ~A ~B
As you can see, the static member of B is destroyed before the actual instance of B.
Example #2:
#include <iostream>
struct A {
A() { std::cout << "*A "; };
~A() { std::cout << "~A "; };
};
struct B {
B() { std::cout << "*B "; };
~B() { std::cout << "~B "; };
static A a;
};
A B::a;
B t;
int main() {}
// Output: *A *B ~B ~A
Here the reverse is true. It's a cheap fix for your current issue, but my advice is to avoid static instances altogether; you'll only fall into more static initialisation pitfalls like this down the line... possibly with a future incarnation of the same code!

If you are having these kinds of problems with a static, it must mean that MyClass also has static scope and you can't design code like this with one static accessing the other. It might work and it might not work since you have a problem with the order of destruction.
It's also entirely possible that you have another global (static) causing memory corruption. If this is the case it might mean that overwriting one global might overwrite other near by globals residing in the same memory space, i.e. the static you are having problems with has been corrupted and not deleted.

Related

Removing an object from a singleton-managed container upon destruction

I have a Singleton class that manages a container of Items, exposing public functions that allow Items to be added or removed from the container.
class Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
public:
static Singleton& Instance()
{
static std::unique_ptr<Singleton> Instance(new Singleton);
return *Instance;
}
void Add(ItemPtr item)
{
mContainer.push_back(item);
}
void Remove(ItemPtr item)
{
for (auto it = mContainer.begin(); it != mContainer.end(); it++)
if (*it == item)
mContainer.erase(it);
}
private:
std::vector<ItemPtr> mContainer;
};
I'd like Item to have the ability to add itself to the Singleton container via an Add() method, and remove itself from the container upon its destruction.
class Item
{
public:
Item() {}
~Item()
{
Singleton::Instance().Remove(ItemPtr(this));
}
void Add()
{
Singleton::Instance().Add(ItemPtr(this));
}
};
When I run the example below, I get a crash on Singleton::Remove(), specifically a EXC_BAD_ACCESS on mContainer.begin().
int main()
{
Item* a = new Item();
Item* b = new Item();
a->Add();
b->Add();
delete a;
delete b;
}
This seems to indicate that mContainer no longer exists. Looking at the call stack, I can also see one of the root call stack frames is the destructor Singleton::~Singleton(), which would explain why mContainer is no longer there.
I've tried a different approach : instead of using std::shared_ptr<Item> I simply used raw pointers (i.e., Item*) with the appropriate substitutions in the code. It worked without problems.
My questions are:
I guess what's happening is that the ownership of the Item objects is only released by the shared_ptr after the destruction of Singleton, which causes the error. Is this correct?
Is it impossible to do what I want to do if the container in Singleton is of shared_ptr<Item>?
If not, how could I do it?
The wisdom of doing this in the first place notwithstanding, what you want can be achieved if you're willing to use, and abide by the restrictions of, std::enabled_shared_from_this. See below:
#include <iostream>
#include <algorithm>
#include <memory>
#include <vector>
struct Item;
typedef std::shared_ptr<Item> ItemPtr;
class Singleton
{
private:
Singleton() {}
public:
static Singleton &Instance()
{
static Singleton s;
return s;
}
void Add(ItemPtr item)
{
mContainer.emplace_back(std::move(item));
}
void Remove(const ItemPtr& item)
{
mContainer.erase(
std::remove(mContainer.begin(), mContainer.end(), item),
mContainer.end());
}
void Clear()
{
mContainer.clear();
}
private:
std::vector<ItemPtr> mContainer;
};
// note derivation. this means you can get a std::shared_ptr<Item>
// via `shared_from_this` , but it also means the object itself
// MUST be an actual shared object to begin with.
struct Item : public std::enable_shared_from_this<Item>
{
void Add()
{
Singleton::Instance().Add(shared_from_this());
}
};
int main()
{
ItemPtr a = std::make_shared<Item>();
ItemPtr b = std::make_shared<Item>();
// add to the singleton container
a->Add();
b->Add();
// report reference count of 'a'
std::cout << "before removal 'a' has " << a.use_count() << " references\n";
Singleton::Instance().Remove(a);
std::cout << "after removal 'a' has " << a.use_count() << " references\n";
}
Output
before removal 'a' has 2 references
after removal 'a' has 1 references
The most important part of this is the creation of a and b in main . Notice they are, in fact, managed by std::shared_ptr enshrouding from inception. This is required for std::enable_shared_from_this to work correctly. The rest is fairly straight forward. The ability to get a reference-bumped std::shared_ptr from within the body of any member of Item is done via the shared_from_this() member provided from the base class std::enable_shared_from_this.
In short, taking this approach will work for you, but at no point can you use shared_from_this() unless the object it is being fired upon is already managed by a std::shared_ptr in the first place. Keep that in mind.

How to initialize member variable with super class type depending on constructor argument?

After searching for hours, I end up here. I have a Container class with a pointer to Base class as member variable. This should either refer to Spec1 or another inherited classes of Base, which I omitted here. The type should be determined by the argument in constructor (e.g. string, enum, int, etc.).
I read much about dynamic memory allocation and why it should be avoided whenever possible. Is it possible to avoid here? Isnt any usual object destroyed after the constructor? Or is the design idea completely wrong? I come from Java :( Thanks in advance.
class Base{
public:
virtual ~Base(){}; // required?
virtual void doSomething() = 0;
};
class Spec1 : public Base {
public:
Spec1(){};
Spec1(int i){
// whatever
}
void doSomething(){
std::printf("hello world");
}
};
class Container{
public:
Container(String type_message){
if (type_message.compare("We need Spec1")){
m_type = new Spec1(1);
} // add more ifs for other types (Spec2, Spec3 etc.)
}
void doSomethingWithSpec(){
m_type->doSomething();
}
private:
Base* m_type;
};
int main (int argc, char **argv){
Container a ("We need Spec1");
a.doSomething();
}
Requiring Container to be aware of every possible derived class of Base does not sound like good design. That is what factory functions are for.
Have Container store that object as std::unique_ptr to avoid memory leaks and manual memory management.
struct Base {
virtual ~Base() = default;
virtual void doSomething() = 0;
};
struct Spec1 : Base {
void doSomething() override {
std::printf("%s\n", __PRETTY_FUNCTION__);
}
};
// Factory function.
std::unique_ptr<Base> createBase(std::string const& type) {
if(type == "Spec1")
return std::unique_ptr<Base>(new Spec1);
throw std::runtime_error("Unknown type " + type);
}
class Container {
std::unique_ptr<Base> m_type;
public:
Container(std::string const& type)
: m_type(createBase(type))
{}
void doSomething(){
m_type->doSomething();
}
};
int main() {
Container a ("Spec1");
a.doSomething();
}
Constructor works like any other function. Local variables are allocated in stack and get out of scope whenever the function completes whereas dynamic memory allocation is done in stack and needs to be explicitaly deallocated (in C++ and not in Java) before the function completes.
However in your case
m_type = new Spec1(1);
new Spec1(1) is dynamically allocated in heap and won't get destroyed on completion of Constructor code. The reference is stored in the member variable of the class. So as long as the instance of class Container is in scope, the memory allocated to Spec1(1) can be referred.
To compare just consider other scenario.
Container(String type_message){
Base* m_type;
if (type_message.compare("We need Spec1")){
m_type = new Spec1(1);
} // add more ifs for other types (Spec2, Spec3 etc.)
}
Here as soon as constructor finishes, m_type will go out of scope but new Spec1(1) will still be there in heap as the memory leak.

Creation of objects only in Manager class

I want to create a manager class which shall manage all the created objects of one type. Naturally this class should also create these objects. Therefore the client isn't allowed to create objects by himself, but instead must always use the manager class to do it.
Additionally the client is allowed to define his own classes which will be managed by one Manager.
template<class Type>
class Manager{
//...
Type* createInstance(){
Type* ptr = new Type();
//do sommething
return ptr;
}
};
The problem is: How do I restrict the creation of instances only to the manager class?
One possibility would be to declare the constructor as private and the Manager class as a friend class:
class A{
friend class Manager<A>;
private:
A(){}
~A(){}
};
Since the client is allowed to define own classes he could just declare the constructor public and the manager would still work without any problems. But the client would be able to create instances of those classes without the manager class witnessing it, resulting in bad behaviour/ressource management of the framework.
Is there a way to overcome this problem?
Managers of this sort are usually a bad pattern. The following code sample shows why.
It's the same problem as the one that says all destructors should be virtual. I use Manager to create a B, which derives from A, assign the object into an A* pointer. If it's destroyed as such, it goes through Manager::destroy(), which will probably not end well since it was created via Manager::make()
#include <iostream>
using namespace std;
template<class Type>
class Manager
{
public:
Manager(char *type)
{
mytype = type;
}
Type *make()
{
Type *ptr = new Type();
cout << "in Manager<" << mytype << ">::make() ptr->mytype is " << ptr->mytype << endl;
return ptr;
}
void destroy(Type *ptr)
{
cout << "in Manager<" << mytype << ">::destroy() ptr->mytype is " << ptr->mytype << endl;
delete ptr;
}
private:
char *mytype;
};
class A
{
friend class Manager<A>;
protected:
A()
{
mytype = "A";
cout << "in A()" << endl;
}
virtual ~A()
{
cout << "in ~A() mytype is " << mytype << endl;
}
char *mytype;
};
class B : public A
{
friend class Manager<B>;
protected:
B()
{
mytype = "B";
cout << "in B()" << endl;
}
virtual ~B()
{
cout << "in ~B() mytype is " << mytype << endl;
}
};
int main()
{
Manager<A> ma("A");
Manager<B> mb("B");
B *b = mb.make();
A *a = b;
ma.destroy(a); // This line calls Manager<A>::destroy. It should call Manager<B>::destroy.
return 0;
}
which produces the following as output:
in A()
in B()
in Manager<B>::make() ptr->mytype is B
in Manager<A>::destroy() ptr->mytype is B -- Oops - wrong destroy.
in ~B() mytype is B
in ~A() mytype is B
Which in turn means you can't use inheritance to it's full capability, which really defeats the purpose of using an OO language in the first place.
Depending on why you think you need a manager, there is probably a better solution.
If it's for memory management (unlikely given your original code snippet), overriding new and delete is worth taking a look at.
If it's for keeping track of all instances for processing purposes (e.g. objects in a game that get updated every game tick) then while it's a bit of a mental gearshift, a better solution is to integrate the manager into the class itself, as a set of static member functions and variables. Managers of this sort are almost invariably singletons, so making them static members / functions gets you to the same place semantically.
So you might have:
static set<A *> s_collection;
static void Heartbeat() // in class A
{
// lock s_collection here
for (auto it = s_collection.begin, end = s_collection.end() it != end; ++it)
{
// process *it
}
// unlock s_collection here
}
and then during A::A() you insert this into s_collection, and likewise during A::~A() you erase this.
Just be careful to use suitable synchronization primitives if you're multithreaded since most stl containers are not inherently thread safe.
You could use some variation of the passkey pattern to achieve this:
http://coliru.stacked-crooked.com/a/257860767a74a15e

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.

Use of static collections within a class to store class

I am reviewing some code and a common pattern I am seeing is where a collection of objects is stored as a static member of the class of object being stored.
If, for example, I have a class of objects: class widget, then a list of widgets would be stored as a static std::list within the widget class.
The obvious way to do this would be to have an application level (global level) std::list - and then to find an item lookup this application level list.
I can see that the static member collection idea is more convenient for the user of a. Are there other advantages? Are there other alternatives which should also be considered similar? What are the pros and cons of a and b approach?
Here are the two alternatives in code:
file a.hpp:
//Using collection as static member of class idea
class a {
public:
a();
~a();
class id2a_map;
static class id2a_map id_map;
static a* Find(unsigned id);
unsigned m_id;
};
file a.cpp:
#include <map>
#include "a.hpp"
class a::id2a_map : public std::map<int, a*>
{
};
a::id2a_map a::id_map;
a::a() {
static unsigned id_cnt = 0;
++id_cnt;
id_map.insert(id_map.end(), id2a_map::value_type(m_id = id_cnt, this));
}
a::~a() {
id_map.erase(m_id);
}
a* a::Find(unsigned id) {
id2a_map::iterator i = id_map.find(id);
return i==id_map.end() ? 0 : i->second;
}
file b.hpp:
// b class - not using static collection
class b {
public:
b(unsigned id) : m_id(id) { }
unsigned get_id() const { return m_id; }
private:
unsigned m_id;
};
file main.cpp to exercise a and b:
#include <iostream>
#include <map>
#include "a.hpp"
#include "b.hpp"
int main() {
// approach using static map within class
a obj1;
a obj2;
a obj3;
a obj4;
a* fnd = a::Find(2);
std::cout << "object with id 2 " << (fnd ? "" : "not ") << "found\n";
// application level map
std::map<unsigned, b*> id2b_map;
unsigned id = 0;
b obj5(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj5));
b obj6(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj6));
b obj7(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj7));
b obj8(++id);
id2b_map.insert(id2b_map.end(), std::make_pair<unsigned, b*>(id, &obj8));
std::map<unsigned, b*>::iterator i = id2b_map.find(2);
std::cout << "object with id 2 " << (i == id2b_map.end() ? "not " : "") << "found\n";
return 0;
}
I can see that the static member collection idea is more convenient for the user of a.
It is not more convenient, except for simple cases. Adding a static map of instances means you add a hidden dependency. Are there any use cases when you do not need this list? If you place it as a static private instance, you will always have it there (whether you use it or not).
Also, the code you wrote, will have unexpected results here:
class a::id2a_map : public std::map<int, a*>
std::map is not written to be inherited, which means it doesn't have a virtual destructor. When the class gets destroyed, it's destructor may not get called (compiler-dependent).
Are there other alternatives which should also be considered similar? What are the pros and cons of a and b approach?
B approach is better, but not as good as it could be. The implementation will not depend on std::list (minimizing dependencies is always a plus) but the list has pointers, and it shouldn't.
Could you write something like this instead?
class a {
public:
a();
~a();
unsigned m_id; // same as in your example
};
client code:
std::map<unsigned, a> instances; // not static; if you need it somewhere else,
// just pass it in as a parameter
a instance;
instances[a.m_id] = std::move(a);
// use instances.find from here on
The code is straight-foward, minimal and doesn't break SRP.
In the case of static members, if you have static methods doing something with them, since the compiler knows all about what the methods will do at compile time, it has a better chance to optimize them well. Depending on the compiler, the amount of optimization varies.
This is an interesting thread of discussion:
http://bytes.com/topic/c/answers/617238-static-functions-better-optimized-compilers