c++ - Best way to instantiate different object types according to value? -


i'll simplify problem of hundreds of classes count of 2 , try explain mean:

class base { }; class a: public base { }; class b: public base{ };  static base* foo (int bar){      switch (bar) {         case 0:             return new a();             break;                       case 1:             return new b();             break;         default:             return new base();     } } 

i want instantiate objects according value of bar. feel switch-case isn't best way in c++ way more inheritors of base .

edit: going std::map approach came this:

struct dictionary {     typedef base* (dictionary::*functionpointer)(void);     std::map <int, functionpointer> fmap;      dictionary() {         fmap.insert(std::make_pair(0, new a()));         fmap.insert(std::make_pair(1, new b()));     }      base* call (const int i){         functionpointer fp = null;         fp = fmap[i];         if (fp){             return (this->*fp)();         } else {             return new base();         }     } };  static dictionary dictionary; 

a lot depends on circumstances, frequent solution use static instance of map factory functions. if key type of map small integer value, in example, "map" can nothing more c style array:

static base* foo( int bar ) {     static base* (*factories[])() = [ &afactory, &bfactory ];     return bar >= 0 && bar < size( factories )         ? (*factories[bar])()         : basefactory(); } 

more generally, can use std::map (to discriminate on imaginable type), , can map static instances of factory objects, rather factory functions, if different keys should result in same type, different arguments.

edit:

some suggestions improve dictionary::call function:

base* dictionary::call( int ) const {     std::map<int, functionpointer>::const_iterator                         entry = fmap.find( );     return entry == fmap.end()         ? new base()         : (this->*(entry->second))(); } 

i've made function const, since doesn't modify anything, , impprtantly, use std::map<>::find, avoid inserting entries map if object isn't there.

and since i'm adding const, you'll have update typedef:

typedef base* (dictionary::*functionpointer)() const; 

another suggestion: unless factory functions need access dictionary, make them static. syntax lot simpler (and improve performance). static changes typedef again:

also: in constructor, new a() not function constructing new object. there may facilitate in c++11 (between lambda , std::function), otherwise, you'll still have write each of factory functions hand. or use template:

template <typename target> base* construct() const {     return new target(); }  dictionary() {     fmap.insert( std::make_pair( 0, &dictionary::construct<a> ) );     //  ... } 

or if make them static:

typedef base* (*functionpointer)();  //  ... template <typename target> static base* construct() {     return new target(); }  base* dictionary::call( int ) const {     std::map<int, functionpointer>::const_iterator                         entry = fmap.find( );     return entry == fmap.end()         ? new base()         : (*entry->second)(); } 

you'll notice how static simplifies declarations (and function call through pointer—your pointer member function has become simple pointer function).


Comments

Popular posts from this blog

c# - DetailsView in ASP.Net - How to add another column on the side/add a control in each row? -

javascript - firefox memory leak -

Trying to import CSV file to a SQL Server database using asp.net and c# - can't find what I'm missing -