Related
I have been stumbling over this issue for a while now where I end up wanting to separate the data from the class I want to make and turn it into a pointer in the class.
Say for example I wanted to create an Item Class for an RPG game I keep trying to go:
class ItemTemplate
{
public:
enum TYPE { //Item types here. };
//ctor's and methods here.
private:
std::string m_name;
int m_buyprice;
int m_sellprice;
TYPE m_type;
int m_maxUses;
}
Basically the ItemTemplate is used to define any data that is constant for all instances of any Item object of that type like so:
const ItemTemplate cPotionTemplate( "Potion" , HEALING , 300 , 50 , 3 );
says all potions are called "Potion", are of the HEALING item types, cost 300G and sell for 50g and have 3 uses to start. None of that data is ever going to change. It would probably be more accurate for it to be HealingItemTemplate and to also say how much it recovers but that's getting off the point.
After that I want to create another class
class Item
{
public:
//ctors and methods here.
private:
ItemTemplate* m_Data;
int m_usesLeft;
}
Basically this just accesses the data in the ItemTemplate and tracks the number of uses the item still has.
What I am trying for is to cut down on the number of variables existing in memory when the program is running.
I know I could bundle all of this data into a single class but that would mean that every item would store a copy of data that doesn't or shouldn't change.
Taking sizeof(int) to be 4, sizeof(type) to be 4, sizeof(string) to be 4 and sizeof( a pointer ) to be 4.
The way I keep trying to implement it uses 8 bytes for each instance of an item but doing the bundled way would use 24 + ( m_name.capacity() or m_name.size() * sizeof(char) ) I know the latter doesn't accurately account for reserved space, but I'm not sure of the former.
Regardless, bundling all the data together in one class would use a minimum of 3x the number of bytes separating the data does. What I am struggling to understand is the downside of such an approach. My current thoughts are that it would be an increase in function calls and copies of data being made. I'm thinking that making the Item class a friend of the ItemTemplate class would be able to eliminate what I would consider a large portion of that increase in calls, those to the accessors.
Basically I'm just really struggling to fully understand the downside of the trade-off I keep wanting to make.
So what are the possible drawbacks to using such an implementation?
What methods exist to help determine when such an implementation is still worth using? If it matters for this I am using Code::Blocks 13.12 IDE but am woefully un-knowledgeable when it comes to using debuggers.
Is there another way to achieve this behavior that I'm missing?
I had considered templates but that seemed too rigid in terms of storing them as each derivation of the ItemTemplate class would create a new type Item<Derived Class> and no Item<type> would be able to be stored together unless they were from the same derivation. Which could work for some systems but isn't the desired implementation as it would make adding new Itemtypes much more of a chore.
An interface class in C++ would solve your concerns regarding the templates:
class ItemInterface
{
public:
enum TYPE { potion, scroll };
//ctor's and methods here.
public:
virtual std::string getName();
virtual int get_buyprice();
virtual int get_sellprice();
virtual TYPE get_type();
virtual int get_maxUses();
};
template<ItemInterface::TYPE T>
class item : ItemInterface {
private:
//Note, not all static members need to be constant
static const std::string m_name;
static const int m_buyprice;
static const int m_sellprice;
static const TYPE m_type;
static const int m_maxUses;
int m_usesLeft;
public:
item();
/*your getters implementation here*/
std::string getName(){return m_name;}
//etc...
};
//Your specialisations here.
//This looks ugly because it's private and const.
//Public static initialization would look better.
template<> const std::string item<ItemInterface::potion>::m_name = "potion";
//...
template<> const std::string item<ItemInterface::scroll>::m_name = "scroll";
You have identified two designs from the design patterns book.
Prototype pattern
Flyweight pattern
Prototype pattern
wikipedia prototype pattern
This assumes the construction of things can be achieved by defining available attributes and constructing a prototype. It simplifies the amount of subclassing needed, as the difference is only the parameters to the object.
Flyweight pattern
wikipedia : flyweight pattern
This pattern identifies that the state of many instanced objects may be split between "all these are the same" and these are the movable/usable attributes.
You are right to identify that these patterns have both advantages, and disadvantages, but whether they are appropriate, is based on your usage, not easy for people outside of your project to answer.
I have a class that has the following variables/members:
First Name
Last Name
Age
Address
etc..
I want to create getter-methods for each of them that returns the values. This could become quite large depending on the class.
Is there a quicker or more object-oriented way that would allow me to do this just using one method? The only way I can think about is to have a method that takes a parameter of the name of the variable to be returned; however, the types for the method would change depending on if it was returning a string, int etc..
Does anyone have a solution?
Why do you need those values outside the class? If you have code that is not in Person that calls 4 or 5 Person GetWhatever() methods and glues the strings together, stuffs commas between them and so on, move that code into Person. Do that enough and no code outside Person needs to call your getters.
Some classes are logic-free, they just hold values, and they expect outside objects to do all the work. In C++, using a struct for that makes your intention clear. If you insist that code outside Person needs to arbitrarily access elements of Person, it's probably a struct, not a class. If you insist it's a class, prove it by adding some actual business logic to it.
No, there is no "better" way which is still object-oriented. You should define one public "getter" method for each private member variable which needs to be access outside the class. You should also define a setter method, if the variable is meant to be set from outside the class.
If you want easy to define setter/getter - make it on single member level. Make member template with setter/getter and define is as public element of your class:
template <class Type>
class Member {
public:
Member(const T& value = T()) : value(value) {}
void setValue(const Type& t) { value = t; }
T getValue() const { return value; }
private:
T value;
};
Use it in your class:
class Person {
public:
Member<std::string> firstName;
Member<std::string> lastName;
Member<std::string> address;
Member<unsigned> age;
};
And usage:
int main() {
Person one;
one.firstName.setValue("Joe");
one.age.setValue(33);
}
If your need some constraints (like range checking) then define some RangeCheckingMember template. If you need the members to be dependent on each others - then make relationship between them by pointers/references.
Consider making that parameter lookup using a template member function that takes a default value in a given type.
template<typename ValueType>
const ValueType& get(const KeyType& key, const ValueType& default value) {
...
};
You still have to enumerate (or otherwise list) a KeyType of all your values (or use std::string which might be fine in larger cases) and work back and forth with your storage on the ValueType.
So, this doesn't really help you much until you decide you need arbitrarily large or completely dynamic values. At this point, you need to implement a map which can hold any type which requires either hideous unions or a template wrapper derived class from a common base class used in the map.
The upside to this is that a getKeys() method can present all of the keys available in the class -- something quite useful for dynamic GUIs and message handling.
If you are using a library in which everything subclasses some Object class (QObject for example), you can use a map of (string, object) to hold all your data and then access it with:
Object get(string name) { return memebers[name]; }
members is std::map<std::string, Object>
You will need to use type casts of course.
Button* my_var = static_cast<Button*>(my_class.get("my_button"));
// get returns Object
You can also use Qt's property system if you use Qt. This is not standard c++, but qmake and moc work on many operating systems.
all right.since you know what you want.
void get(int flag, void *return_value)
get the return_value typd casting to what you want.
thanks
It appeared that this problem is quite common in our job.
We we are sending an int or enum value through the network, then we receive it we would like to create/call a particular object/function.
The most simply solution would be to use the switch statement, like below:
switch (value) {
case FANCY_TYPE_VALUE: return new FancyType();
}
It works fine, but we would have plenty of these switch blocks, and when we create new value and type, we would need to change all of them. It does seem right.
Other possibility would be to use the templates. But we cannot, since the value of enum is defined in runtime.
Is there any right design pattern for that, or any right approach?
It seems like a very general and common problem in every day coding...
Try a map:
struct Base { };
struct Der1 : Base { static Base * create() { return new Der1; } };
struct Der2 : Base { static Base * create() { return new Der2; } };
struct Der3 : Base { static Base * create() { return new Der3; } };
std::map<int, Base * (*)()> creators;
creators[12] = &Der1::create;
creators[29] = &Der2::create;
creators[85] = &Der3::create;
Base * p = creators[get_id_from_network()]();
(This is of course really crude; at the very least you'd have error checking, and a per-class self-registration scheme so you can't forget to register a class.)
You can actually do this with some template trickery:
#include <map>
template <typename Enum, typename Base>
class EnumFactory {
public:
static Base* create(Enum e) {
typename std::map<Enum,EnumFactory<Enum,Base>*>::const_iterator const it = lookup().find(e);
if (it == lookup().end())
return 0;
return it->second->create();
}
protected:
static std::map<Enum,EnumFactory<Enum,Base>*>& lookup() {
static std::map<Enum,EnumFactory<Enum,Base>*> l;
return l;
}
private:
virtual Base* create() = 0;
};
template <typename Enum, typename Base, typename Der>
class EnumFactoryImpl : public EnumFactory<Enum,Base> {
public:
EnumFactoryImpl(Enum key)
: position(this->lookup().insert(std::make_pair<Enum,EnumFactory<Enum,Base>*>(key,this)).first) {
}
~EnumFactoryImpl() {
this->lookup().erase(position);
}
private:
virtual Base* create() {
return new Der();
}
typename std::map<Enum,EnumFactory<Enum,Base>*>::iterator position;
};
This allows you to create a new derived object from a given enum, by saying
// will create a new `FancyType` object if `value` evaluates to `FANCY_TYPE_VALUE` at runtime
EnumFactory<MyEnum,MyBase>::create(value)
However, you have to have some EnumFactoryImpl objects, which could be static in some function or namespace.
namespace {
EnumFactoryImpl<MyEnum,MyBase,Derived1> const fi1(ENUM_VALUE_1);
EnumFactoryImpl<MyEnum,MyBase,Derived2> const fi2(ENUM_VALUE_2);
EnumFactoryImpl<MyEnum,MyBase,Derived3> const fi3(ENUM_VALUE_3);
EnumFactoryImpl<MyEnum,MyBase,FancyType> const fi1(FANCY_TYPE_VALUE); // your example
}
These lines are the single point where your source code maps enum values to derived types. So you have everything at the same location, and no redundancy (this eliminates the problem of forgetting to change it in some places, when adding new derived types).
One option is to maintain a dictionary of creators(which has the same interface) that can create a concrete type. Now the creation code will search in the dictionary for an int value (resulting from the enum sent from the client) and call the create method, which returns the concrete object via a base-class pointer.
The dictionary can be initialized at one place with the concrete creators corresponding to each possible enum values.
The problem here is that you have to extend this dictionary initialization code when you add a new type of object. A way to avoid is as following.
Let the creator look for a singleton factory instance and register itself in the constructor with the type enums(integers) with which it can create a concret object.
Create a DLL for one/set of creators and have a global instance of the creators.
The name of the DLL can be entered in a config file which is read by the factory in the initialization. The factory loads all the DLLs in this file and this results in the creation of the static objects which registers themselves with the factory.
Now the factory has the map of all the type enums which it can create with the concrete object creators.
The same object creator look-up mechanism is implemented to create the objects.
Now, the factory doesn't need to be extended at all since step 3,4 and 5 doesn't change for new objects introduced. Step 1 can be implemented in one place.
Only thing you need to do is to add a global object for each of the new concrete type which should be there since the C++ doesn't support reflection natively.
kogut, I don't propose this as an answer, but since you ask me to expand on my comment on your original question here's a very brief summary of what the .net environment gives you...
public enum MyEnum
{
[MyAttribute(typeof(ClassNone))]
None,
[MyAttribute(typeof(ClassOne))]
One,
[MyAttribute(typeof(ClassTwo))]
Two,
[MyAttribute(typeof(ClassThree))]
Three
}
So you have your basic enum One, Two, Three etc. which works just like....er....an enum!
But you also code up a class called MyAttribute (and in fact for more information in this area, just search for Attributes). But as you can see this allows you to say, at design time, that such-and-such an enum value is associated with such-and-such a class.
This information is stored in the enum's metadata (the value of a managed environment!) and can be interrogated at runtime (using Reflection). Needless to say this is very powerful, I've used this mechanism to systematically strip out loads of maps of the kind proposed in other answers to your question.
An example of the usefulness is this...at one client I worked with, the convention was to store statuses as strings in a database on the grounds that they would be more readable to a human who needed to run a table query. But this made no sense in the applications, where statuses were pushed through as enums. Take the above approach (with a string rather than a type) and this transform happened on a single line of code as data was read and written. Plus, of course, once you've defined MyAttribute it can be tagged onto any enum you like.
My language if choice these days is c# but this would also be good in (managed) c++.
I am trying to do a simple class to unique ID conversion. I am thinking about adding a static method:
class A {
static int const *GetId() {
static int const id;
return &id;
}
};
Each class would then be identified by unique int const *. Is this guaranteed to work? Will the returned pointer really be unique? Is there any better simpler solution?
I have also thought about pointer to std::type_info:
class A {
static std::type_info const *GetId() {
return &typeid(A);
}
};
Is that better?
Edit:
I don't need to use the id for serialization. I only want to identify a small set of base classes and I want all subclasses of some class to have the same id
Yes, this will work. Each static local will be given distinct memory location at the time when the module is loaded and it will persist until the module is unloaded. Remember, static locals are stored in static storage that is distributed during compilation and they persist till the module gets unloaded, so they will have distinct memory locations.
The address of static variable is guaranteed to be unique and the same in all translation units.
It is not a good idea because it requires you to add code to every class to be identified.
The pointers to type info objects are not guaranteed to be unique, but the type info objects themselves are guaranteed to compare as equal for a given class, and as unequal for distinct classes. This means you can use small wrapper objects that carry type info pointers, and the delegate the comparisions to the type info objects. C++11 has such a wrapper in the standard library, and if you don't have access to that, there is one in Andrei Alexandrescu's "Modern C++ Design", and therefore probably also in the Loki library, there is probably one in Boost, and there is one on my Wordpress blog – it's not like you to have invent one from scratch.
If, however, the id's are to be used for serialization, then you need id's that are valid across builds. And in that case you you need strings or UUIDs. I would go with UUIDs.
To associate a class with an UUID you can in general use a type traits class. Or if you're only doing Windows programming then you can use Visual C++'s language extensions for this. I think but I am not 100% sure that those language extensions are also implemented by g++ (in Windows).
Cheers & hth.
As I have noticed at least MSVC 2008 or 2010 optimizes the static variable, so that the following GetId function returns same address even for different classes.
static int const *GetId() {
static const int i = 0;
return &i;
}
Therefore address of uninitialized constant static variable may not be used for identification. The simplest fix is to just remove const:
static int *GetId() {
static int i;
return &i;
}
Another solution to generate IDs, that seems to work, is to use a global function as a counter:
int Counter() {
static int i = 0;
return i++;
}
And then define the following method in the classes to be identified:
static int GetId() {
static const int i = Counter();
return i;
}
As the method to be defined is always the same, it may be put to a base class:
template<typename Derived>
struct Identified {
static int GetId() {
static const int i = Counter();
return i;
}
};
And then use a curiously recurring pattern:
class A: public Identified<A> {
// ...
};
The address of the static int is guaranteed to be unique for each
function (and the same for every call to the same function). As such,
it can work very well as an id within a single execution of the code.
The address could conceivably change from one run to the next, and will
often change from one compilation to the next (if you've changed
anything in the code), so it is not a good solution for an external id.
(You don't say whether the id must be valid outside a single execution
or not.)
The address of the results of a typeid is not guaranteed to be the
same each time you call the function (although it probably will be).
You could use it to initialize a pointer, however:
static std::type_info const& GetId()
{
static std::type_info const* id = &typeid(A);
return id;
}
Compared to using int*, this has the advantage of providing additional
information (e.g. for debugging). Like int*, the identifier may be
different from one run to the next; A::GetId()->name() will point to
the same '\0' terminated string (although again the address might be
different) provided you compile with the same compiler. (As far as I
can tell, the standard doesn't guarantee this, but in practice, I think
you're safe.) Change compilers, however, and all bets are off.
The solution I've used in the past is something like:
static char const* GetId()
{
return "A"; // Or whatever the name of the class is.
}
This provides a unique identifier, easily compared, within a single
execution of the code, and a string value which can be used as an
external identifier, and which is guaranteed across all compilers. We
implemented this as a macro, which defined both the static function, and
a virtual function which returned it, e.g.:
#define DECLARE_IDENTIFIER(name) \
static char const* classId() { return STRINGIZE(name); } \
virtual char const* id() { return classId(); }
This results in a very fast (but limited) RTTI, and supports external
identifiers for serialization and persistency.
The int* method would be unique, since a different static memory cell must be allocated for each static variable, and I'd guess it is simpler to understandthan the type_info idea.
Clearly pointers to different variables must have different values. Just watch out if you choose to derive a subclass of A. You need to decide what your policy is for id. If you did nothing then the subclass would have the same id.
In general, you really really want to avoid hacky things like this. If I really had to do this, I'd look at using some UUID system (there's a library in Boost for that, but I'm not very familiar with it), or some singleton that maintained a list of these objects for whatever purpose you need.
Static variables are initialized before Heap & Stack memory so yeah it will be unique.
Quirky though.
Because you will have to add this method to all classes that require a UID you may as well do this.
unsigned int getUID()
{
return 12;
}
The advantage of this is that the compiler will be able to use a jump table if you are using this for RTTI for switching on type, which will not be possible with two pointers because the jump table would be very sparse.
The (minor) disadvantage is you need to keep track of which identifiers have been taken.
A major disadvantage of the first method you presented is that the same numbers cannot be used to identify objects because the virtual getUID() method won't be able to take the address of the variable in another function's scope.
I'm building an hierarchy of objects that wrap primitive types, e.g integers, booleans, floats etc, as well as container types like vectors, maps and sets. I'm trying to (be able to) build an arbitrary hierarchy of objects, and be able to set/get their values with ease. This hierarchy will be passed to another class (not mentioned here) and an interface will be created from this representation. This is the purpose of this hierarchy, to be able to create a GUI representation from these objects.To be more precise, i have something like this:
class ValObject
{
public:
virtual ~ValObject() {}
};
class Int : public ValObject
{
public:
Int(int v) : val(v) {}
void set_int(int v) { val = v);
int get_int() const { return val; }
private:
int val;
};
// other classes for floats, booleans, strings, etc
// ...
class Map : public ValObject {}
{
public:
void set_val_for_key(const string& key, ValObject* val);
ValObject* val_for_key(const string& key);
private:
map<string, ValObject*> keyvals;
};
// classes for other containers (vector and set) ...
The client, should be able to create and arbitrary hierarchy of objects, set and get their values with ease, and I, as a junior programmer, should learn how to correctly create the classes for something like this.
The main problem I'm facing is how to set/get the values through a pointer to the base class ValObject. At first, i thought i could just create lots of functions in the base class, like set_int, get_int, set_string, get_string, set_value_for_key, get_value_for_key, etc, and make them work only for the correct types. But then, i would have lots of cases where functions do nothing and just pollute my interface. My second thought was to create various proxy objects for setting and getting the various values, e.g
class ValObject
{
public:
virtual ~ValObject() {}
virtual IntProxy* create_int_proxy(); // <-- my proxy
};
class Int : public ValObject
{
public:
Int (int v) : val(v) {}
IntProxy* create_int_proxy() { return new IntProxy(&val); }
private:
int val;
};
class String : public ValObject
{
public:
String(const string& s) : val(s) {}
IntProxy* create_int_proxy() { return 0; }
private:
string val;
};
The client could then use this proxy to set and get the values of an Int through an ValObject:
ValObject *val = ... // some object
IntProxy *ipr = val->create_int_proxy();
assert(ipr); // we know that val is an Int (somehow)
ipr->set_val(17);
But with this design, i still have too many classes to declare and implement in the various subclasses. Is this the correct way to go ? Are there any alternatives ?
Thank you.
Take a look at boost::any and boost::variant for existing solutions. The closest to what you propose is boost::any, and the code is simple enough to read and understand even if you want to build your own solution for learning purposes --if you need the code, don't reinvent the wheel, use boost::any.
One of the beauties of C++ is that these kinds of intrusive solutions often aren't necessary, yet unfortunately we still see similar ones being implemented today. This is probably due to the prevalence of Java, .NET, and QT which follows these kinds of models where we have a general object base class which is inherited by almost everything.
By intrusive, what's meant is that the types being used have to be modified to work with the aggregate system (inheriting from a base object in this case). One of the problems with intrusive solutions (though sometimes appropriate) is that they require coupling these types with the system used to aggregate them: the types become dependent on the system. For PODs it is impossible to use intrusive solutions directly as we cannot change the interface of an int, e.g.: a wrapper becomes necessary. This is also true of types outside your control like the standard C++ library or boost. The result is that you end up spending a lot of time and effort manually creating wrappers to all kinds of things when such wrappers could have been easily generated in C++. It can also be very pessimistic on your code if the intrusive solution is uniformly applied even in cases where unnecessary and incurs a runtime/memory overhead.
With C++, a plethora of non-intrusive solutions are available at your fingertips, but this is especially true when we know that we can combine static polymorphism using templates with dynamic polymorphism using virtual functions. Basically we can generate these base object-derived wrappers with virtual functions on the fly only for the cases in which this solution is needed without pessimizing the cases where this isn't necessary.
As already suggested, boost::any is a great model for what you want to achieve. If you can use it directly, you should use it. If you can't (ex: if you are providing an SDK and cannot depend on third parties to have matching versions of boost), then look at the solution as a working example.
The basic idea of boost::any is to do something similar to what you are doing, only these wrappers are generated at compile-time. If you want to store an int in boost::any, the class will generate an int wrapper class which inherits from a base object that provides the virtual interface required to make any work at runtime.
The main problem I'm facing is how to
set/get the values through a pointer
to the base class ValObject. At first,
i thought i could just create lots of
functions in the base class, like
set_int, get_int, set_string,
get_string, set_value_for_key,
get_value_for_key, etc, and make them
work only for the correct types. But
then, i would have lots of cases where
functions do nothing and just pollute
my interface.
As you already correctly deduced, this would generally be an inferior design. One tell-tale sign of inheritance being used improperly is when you have a lot of base functions which are not applicable to your subclasses.
Consider the design of I/O streams. We don't have ostreams with functions like output_int, output_float, output_foo, etc. as being directly methods in ostream. Instead, we can overload operator<< to output any data type we want in a non-intrusive fashion. A similar solution can be achieved for your base type. Do you want to associate widgets with custom types (ex: custom property editor)? We can allow that:
shared_ptr<Widget> create_widget(const shared_ptr<int>& val);
shared_ptr<Widget> create_widget(const shared_ptr<float>& val);
shared_ptr<Widget> create_widget(const shared_ptr<Foo>& val);
// etc.
Do you want to serialize these objects? We can use a solution like I/O streams. If you are adapting your own solution like boost::any, it can expect such auxiliary functions to already be there with the type being stored (the virtual functions in the generated wrapper class can call create_widget(T), e.g.
If you cannot be this general, then provide some means of identifying the types being stored (a type ID, e.g.) and handle the getting/setting of various types appropriately in the client code based on this type ID. This way the client can see what's being stored and deal set/get values on it accordingly.
Anyway, it's up to you, but do consider a non-intrusive approach to this as it will generally be less problematic and a whole lot more flexible.
Use dynamic_cast to cast up the hierarchy. You don't need to provide an explicit interface for this - any reasonable C++ programmer can do that. If they can't do that, you could try enumerating the different types and creating an integral constant for each, which you can then provide a virtual function to return, and you can then static_cast up.
Finally, you could consider passing a function object, in double-dispatch style. This has a definite encapsulation advantage.
struct functor {
void operator()(Int& integral) {
...
}
void operator()(Bool& boo) {
...
}
};
template<typename Functor> void PerformOperationByFunctor(Functor func) {
if (Int* ptr = dynamic_cast<Int*>(this)) {
func(*ptr);
}
// Repeat
}
More finally, you should avoid creating types where they've basically been already covered. For example, there's little point providing a 64bit integral type and a 32bit integral type and ... it's just not worth the hassle. Same with double and float.