Is there any efficient way in C++ of generating an ID unique to the class, not to the instance? I'm looking for something of this level of simplicity (this generates an ID for every instance, not for every class type):
MyClass::MyClass()
{
static unsigned int i = 0;
id_ = i++;
}
Edit: Why I want unique IDs.
I'm writing a game. All entities in my game will have different states they can be in (walking left, jumping, standing, etc); these states are defined in classes. Each state needs to have its own ID so I can identify it.
You can try this, but it's not-deterministic.
int id_count = 0;
template <typename T>
int get_id()
{
static int id = id_count++;
return id;
}
Then just use:
get_id<int>(); // etc.
Of course, this isn't thread safe.
Again, it's not deterministic: the IDs are generated the first time you call the function for each type. So, if on one run you call get_id<int>() before get_id<float>() then on another run you call them the other way round then they'll have different IDs. However, they will always be unique for each type in a single run.
Basically you are asking for a custom rolled RTTI solution, that you can selectively apply to classes.
This can start from very crude preprocessor stuff like :
#define DECLARE_RTTI_CLASS(a) class a { \
inline const char * class_id() { return #a };
.. to a more sophisticated solutions that track inheritance etc, essentially partially duplicating compiler RTTI functionality. For an example, see Game Programming Gems #2, Dynamic Type Information
Previous discussions on gamedev on the same subject are also worth reading
Use your MyClass as a primitive, and incorporate a static instance of one into each class you want to ID.
class MyOtherClass1 {
static MyClass id;
};
class MyOtherClass2 {
static MyClass id;
};
[etc.]
Related
I'm currently designing classes that should represent a chaotic storage system.
Lets say we have slots in rows and columns with certain properties.
So the slots have different restrictions in min/max height, width, length, weight and some more that come from a parameter file.
Also the Slots have a max total weight that must be checked before a new parcel gets added to that slot. And also the max weight that a row of slots can hold is lower than the sum of the max weights of the single slots. So for example each individual slot might be able to hold 50kg but the row of 10 slots must not exceed 200kg, so it is not allowed to fill every slot by 100%. The same is true for the Columns where the maximum weight is lower than the sum of the individual weights of the single rows. The row_id and column_id are atrificial numbers for adressing the slot in the physical system with barcodes or whatever that get read for positioning.
As all this parameters do not change over the lifetime of the program, my intention was to design the classes in a way that this properties are readable by getter functions but there should not be any setter functions (maybe not even private ones) in the object o the values cannot be changed by accident.
There is one class/function that reads the config-file and generates the data structure for the rows and columns with the slots. This function should be able to read the config and create objects for every column holding a row of slots and pass all the values from the config down to the slot.
Later when the program is running I also need some way to search for the best matching slot to add the next parcel or for searching parcels and unload them in a certain sequence.
So the (simplfied) basic structure of the classes would be like this:
Class Parcel {
int width;
int height;
int length;
int weight;
}
Class Slot {
vector<Parcel> parcel;
int min_width;
int max_width;
int min_height;
int max_height;
int min_length;
int max_length;
int max_total_weight;
int act_total_weight;
int total_length;
int free_length;
}
Class Row {
vector<Slot> slot;
int row_id;
int max_total_weight;
int act_total_weight;
}
Class Column {
vector<Row> row;
int column_id;
int max_total_weight;
int act_total_weight;
}
Class Storage {
vector<Column> column;
}
So here are my thoughts about how to initialize the data structure:
First possibility would be to pass all the properties in the constructor(s) of the classes, but then the constructors has some huge parameter lists specially for the Slot class that has a lot of properties.
Second thing that came to my mind (and currently my fafourite way to go) is to use config-data-structures that hold all the parameters. This parameter-objects get filled by the config-function and passed to the constructor when initializing the class. Then it also may be useful to use the parameter class as such and not having all the parameters defined in the storage class once more.
Third way is to use private setter and public getter and make the config class friends with the data structure classes to be able to access the setter functions (but i would prefer to have no setters at all in the final storage structure classes.
Fourth way that i was thinking off, was to derive child classes from the structure classes that hold the setter functions (and also some other logic needed for creating the data structure) so the child has no own variables but only additional functions. So the child class is used to fill the properties but the base class gets added to the data structure vector.
I also want to use Factory pattern to initialize the data structure because the objects have often similar or only slightly different properties. So with the second aproach after creating one row of slots I would maybe want to change the max weight of the slots in that row. Therefore I would need to change the setting in the factory and the factory then fills the parameter data structure differently and passes it to the Slot class. Or is it better to pass the data structure to the factory directly and the factory assigns it but then i think this is not what the factory pattern is meant to be.
I don't know if this is a good aproach or which of the above is best practice.
Or am I missing something and there is a way more convenient solution or this?
Thank you (and sorry if the question is maybe not the way it should be)
When constructing your classes as you describe it you can have a look at the creational design patterns.
Your second proposed solution is almost a builder design pattern. This will help you to construct the Slot e.g. piecewise.
As an example:
#include <iostream>
class Slot {
public:
int GetMinWidth() const { return min_width_; };
int GetMaxWidth() const { return max_width_; };
// Builder class
class SlotBuilder {
public:
SlotBuilder& SetMinWidth(int min_width) {
min_width_ = min_width;
return *this;
}
SlotBuilder& SetMaxWidth(int max_width) {
max_width_ = max_width;
return *this;
}
Slot Build() {
return Slot(min_width_, max_width_);
}
private:
int min_width_{/* you can add default value here*/};
int max_width_{/* you can add default value here*/};
};
// This is optional, but creates a neat interface
static SlotBuilder Create() {
static SlotBuilder slot_builder;
return slot_builder;
}
private:
// Make constructor private to restrict access and force the use of the builder
Slot(int min_width, int max_width) : min_width_(min_width), max_width_(max_width) {}
const int min_width_;
const int max_width_;
// .
// .
// Continue with your const attributes
};
int main() {
// Create the slot with the builder
Slot slot = Slot::Create()
.SetMinWidth(10)
.SetMaxWidth(20)
.Build();
std::cout << slot.GetMinWidth() << ", " << slot.GetMaxWidth();
return 0;
}
You can see the example working here
For having different types that are almost the same a Prototype pattern could work if you want to "clone" a class or in your case a Factory pattern could do the job.
There is never an ideal solution or that one pattern that solves it all, so I can't give you a definitive answer, but here are some collected thoughts:
Default values
Primitive types like int don't have a default value, so make sure you give them one explicitly:
struct Parcel {
int width{};
int height = 0;
int length = {};
int weight{};
}
All those different versions above are equivalent, but you really should use one of them. Otherwise you will probably run into UB down the line.
Const correctness
One thing that I love about C++ and that I dearly miss in languages like C# is const correctness. If you want an object to be immutable, declare it as const. To prevent changes to your objects, either instantiate the object as a const:
const Parcel x;
x.width = 10; // compiler error
or make the members of your classes const:
struct Parcel {
const int width{};
const int height{};
const int length{};
const int weight{};
};
Parcel x;
x.width = 10; // compiler error
Aggregate initialization
If you keep your types simple enough you can initialize the class members with curly braces directly:
const Parcel x { 1, 2, 3, 4 };
In C++ 20, you can also name the members, so this code is equivalent to the line above:
const Parcel x { .width = 1, .height = 2, .length = 3, .weight = 4 };
Note that this can bite you later though if you have to deal with ABI stability and versioning. In that case you are better off using getter and setter functions, because that allows you to still change the data layout of your members.
I have to think about design patterns a bit more. I'll update this post if something useful comes out of it.
I have classes DBGameAction and ServerGameAction which has common parent class GameAction. Classes DBGameAction and ServerGameAction it's a API for safety working with entity GameAction from different part of program.
My question is: is it normal at first create DBGameAction entity and then cast it to the ServerGameAction entity? Or maybe it's a wrong program design?
My program:
#include <vector>
#include <string>
#include <iostream>
class GameAction
{
protected:
/* Need use mutex or something else for having safety access to this entity */
unsigned int cost;
unsigned int id;
std::vector<std::string> players;
GameAction(){}
public:
unsigned int getCost() const
{
return cost;
}
};
class DBGameAction : public GameAction
{
public:
void setCost(unsigned int c)
{
cost = c;
}
void setId(unsigned int i)
{
id = i;
}
};
class ServerGameAction : public GameAction
{
ServerGameAction(){}
public:
void addPlayer(std::string p)
{
players.push_back(p);
}
std::string getLastPlayer() const
{
return players.back();
}
};
int main(int argc, char *argv[])
{
DBGameAction *dbga = 0;
ServerGameAction *sga = 0;
try {
dbga = new DBGameAction;
}
catch(...) /* Something happens wrong! */
{
return -1;
}
sga = reinterpret_cast<ServerGameAction*>(dbga);
sga->addPlayer("Max");
dbga->setCost(100);
std::cout << dbga->getCost() << std::endl;
std::cout << sga->getLastPlayer() << std::endl;
delete dbga;
sga = dbga = 0;
return 0;
}
It is wrong program design.
Is there a reason why you are not creating GameAction variables which you then downcast to DBGameAction and ServerGameAction?
I haven't used reinterpret_cast in many occasions but I am sure it shouldn't be used this way. You should try to find a better design for the interface of your classes. Someone who uses your classes, doesn't have a way to know that he needs to do this sort of castings to add a player.
You have to ask yourself, if adding a player is an operation that only makes sense for ServerGameActions or for DBGameActions too. If it makes sense to add players to DBGameActions, then AddPlayer should be in the interface of DBGameAction too. Then you will not need these casts. Taking it one step further, if it is an operation that makes sense for every possible GameAction you may ever have, you can put it in the interface of the base class.
I have used a similar pattern effectively in the past, but it is a little different than most interface class setups. Instead of having a consistent interface that can trigger appropriate class-specific methods for accomplishing similar tasks on different data types, this provides two completely different sets of functionality which each have their own interface, yet work on the same data layout.
The only reason I would pull out this design is for situations where the base class is data-only and shared between multiple libraries or executables. Then each lib or exe defines a child class which houses all the functionality that it's allowed to use on the base data. This way you can, for example, build your server executable with all kinds of nice extra functions for manipulating game data that the client isn't allowed to use, and the server-side functionality doesn't get built into the client executable. It's much easier for a game modder to trigger existing, dormant functionality than to write and inject their own.
The main part of your question about casting directly between the child classes is making us worry, though. If you find yourself wanting to do that, stop and rethink. You could theoretically get away with the cast as long as your classes stay non-virtual and the derived classes never add data members (the derived classes can't have any data for what you're trying to do anyway, due to object slicing), but it would be potentially dangerous and, most likely, less readable code. As #dspfnder was talking about, you would want to work with base classes for passing data around and down-cast on-demand to access functionality.
With all that said, there are many ways to isolate, restrict, or cull functionality. It may be worth reworking your design with functionality living in friend classes instead of child classes; that would require much less or no casting.
I'm reading through Martin Fowler's PoEAA right now on object-relational structural patterns. As a project to do while learning them, I thought I'd build a mini eCommerce system in C++. I'm having trouble figuring out how to return the objects from the mapper.
I have a Product base class, which has derived classes Hat and Shirt. Products have a type member to identify which derived class they are. I also have a ProductMapper class, with derived classes HatMapper and ShirtMapper, all of which implement a bunch of finder methods which let me try and retrieve certain hats and shirts.
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
};
// Derived classes don't necessarily have the same members.
class Hat : public Product
{
unsigned char fitted;
unsigned char color;
unsigned char style;
};
class Shirt : public Product
{
unsigned char size;
};
In the logic part of my application where I'd instantiate these mappers and retrieve products is where I'm having trouble. I can instantiate a HatMapper and pull back Hat objects without any problem, same with a ShirtMapper and Shirt objects. The patterns work great in these cases (in particular I'm using class table inheritance, i.e. one product table with product data, one table for hats with hat-specific data, and one table for shirts with shirt-specific data).
My problem is, what do I do if I want to retrieve all products, both hats and shirts? I can instantiate a ProductMapper and fetch all of the product data, but that seems like the wrong approach since I'd have to loop through all the Products I retrieve and build up Hats and Shirts based on their type in my logic portion of the program. Additionally, I'd have to modify any code that handles the situation this way when I add new product types. Seems bad.
The Fowler book has examples of the mappers with the base mapper using the derived mappers which seems completely wrong to me (have to modify the base mapper every time I add a new product, not great). Here's a quick example of how it's done there:
class ProductMapper
{
unsigned long long int productId;
unsigned long long int productType;
HatMapper * hm;
ShirtMapper * sm;
Product * FindById(unsigned long long int id)
{
// Query database for data.
if (this->productType == PRODUCT_TYPE_HAT)
{
return hm->FindById(id); // Hat object.
}
else if (this->productType == PRODUCT_TYPE_SHIRT)
{
return sm->FindById(id); // Shirt object.
}
return NULL;
}
};
Here's how I'd use this in the logic part of my program. Examples of this aren't provided in the book:
ProductMapper * pm = new ProductMapper();
Product * p = pm->FindById(1); // It's a Product, but a Hat or Shirt?
// Have to check type since a Product was returned.
switch (p->type)
{
case PRODUCT_TYPE_HAT:
{
Hat * h = (Hat) p;
break;
}
// Etc. Modify this every time a new product type is added or removed.
}
This will introduce circular dependencies. Additionally, assuming I somehow eliminate the circular dependencies, the result of the HatMapper and ShirtMapper classes are Hat objects and Shirt objects. Thus when I return from the ProductMapper, I'll be downcasting, so I'd have to again manipulate the result in my logic, which again introduces the issue of modifying code when I introduce new product types.
I'm at a loss for what to do. In a perfect world, I'd like to have a Product class and a ProductMapper class, both of which I can extend quickly, introducing new product types without having to modify existing code (at least too much).
I would like to be able to use these patterns from PoEAA, they do seem nice and useful, but I'm not sure if it's just something I can't do in C++ or I'm missing something that's preventing me from doing it. Alternative patterns and approaches are also really welcomed.
It feels like the Type Object pattern could help in this case, I know the link is about game programming but it is sufficient to apply the pattern to other domains.
The problem right now is that if you want to add products you have to add several classes, which can become hard to maintain as you noticed.
Edit: Maybe you could use something like that (code is C++11 to simplify the example):
class ProductProperty
{
typedef std::map<std::string, unsigned char> PropertyMap;
PropertyMap properties;
public:
ProductProperty(std::initializer_list<PropertyMap::value_type> il):
properties(il)
{}
// Use of at() is intended to only deal with the defined properties
const PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop) const
{
return properties.at(prop);
}
PropertyMap::value_type::second_type&
get(const PropertyMap::value_type::first_type& prop)
{
return properties.at(prop);
}
};
// Some helpers to illustrate
std::shared_ptr<ProductProperty> makeHatProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{
{"fitted", ***whatever**},
{"color", ***whatever**},
{"style", ***whatever**}
});
}
std::shared_ptr<ProductProperty> makeShirtProperty()
{
return std::make_shared<ProductProperty>(
ProductProperty{{"size", ***whatever**}}
);
}
class Product
{
unsigned long long int id;
std::string name;
unsigned int type;
std::shared_ptr<ProductProperty> properties;
public:
Product(std::shared_ptr<ProductProperty> props):
properties(props)
{}
// Whatever function you need to get/set/check properties
};
In the code I am now creating, I have an object that can belong to two discrete types, differentiated by serial number. Something like this:
class Chips {
public:
Chips(int shelf) {m_nShelf = shelf;}
Chips(string sSerial) {m_sSerial = sSerial;}
virtual string GetFlavour() = 0;
virtual int GetShelf() {return m_nShelf;}
protected:
string m_sSerial;
int m_nShelf;
}
class Lays : Chips {
string GetFlavour()
{
if (m_sSerial[0] == '0') return "Cool ranch";
else return "";
}
}
class Pringles : Chips {
string GetFlavour()
{
if (m_sSerial.find("cool") != -1) return "Cool ranch";
else return "";
}
}
Now, the obvious choice to implement this would be using a factory design pattern. Checking manually which serial belongs to which class type wouldn't be too difficult.
However, this requires having a class that knows all the other classes and refers to them by name, which is hardly truly generic, especially if I end up having to add a whole bunch of subclasses.
To complicate things further, I may have to keep around an object for a while before I know its actual serial number, which means I may have to write the base class full of dummy functions rather than keeping it abstract and somehow replace it with an instance of one of the child classes when I do get the serial. This is also less than ideal.
Is factory design pattern truly the best way to deal with this, or does anyone have a better idea?
You can create a factory which knows only the Base class, like this:
add pure virtual method to base class: virtual Chips* clone() const=0; and implement it for all derives, just like operator= but to return pointer to a new derived. (if you have destructor, it should be virtual too)
now you can define a factory class:
Class ChipsFactory{
std::map<std::string,Chips*> m_chipsTypes;
public:
~ChipsFactory(){
//delete all pointers... I'm assuming all are dynamically allocated.
for( std::map<std::string,Chips*>::iterator it = m_chipsTypes.begin();
it!=m_chipsTypes.end(); it++) {
delete it->second;
}
}
//use this method to init every type you have
void AddChipsType(const std::string& serial, Chips* c){
m_chipsTypes[serial] = c;
}
//use this to generate object
Chips* CreateObject(const std::string& serial){
std::map<std::string,Chips*>::iterator it = m_chipsTypes.find(serial);
if(it == m_chipsTypes.end()){
return NULL;
}else{
return it->clone();
}
}
};
Initialize the factory with all types, and you can get pointers for the initialized objects types from it.
From the comments, I think you're after something like this:
class ISerialNumber
{
public:
static ISerialNumber* Create( const string& number )
{
// instantiate and return a concrete class that
// derives from ISerialNumber, or NULL
}
virtual void DoSerialNumberTypeStuff() = 0;
};
class SerialNumberedObject
{
public:
bool Initialise( const string& serialNum )
{
m_pNumber = ISerialNumber::Create( serialNum );
return m_pNumber != NULL;
}
void DoThings()
{
m_pNumber->DoSerialNumberTypeStuff();
}
private:
ISerialNumber* m_pNumber;
};
(As this was a question on more advanced concepts, protecting from null/invalid pointer issues is left as an exercise for the reader.)
Why bother with inheritance here? As far as I can see the behaviour is the same for all Chips instances. That behaviour is that the flavour is defined by the serial number.
If the serial number only changes a couple of things then you can inject or lookup the behaviours (std::function) at runtime based on the serial number using a simple map (why complicate things!). This way common behaviours are shared among different chips via their serial number mappings.
If the serial number changes a LOT of things, then I think you have the design a bit backwards. In that case what you really have is the serial number defining a configuration of the Chips, and your design should reflect that. Like this:
class SerialNumber {
public:
// Maybe use a builder along with default values
SerialNumber( .... );
// All getters, no setters.
string getFlavour() const;
private:
string flavour;
// others (package colour, price, promotion, target country etc...)
}
class Chips {
public:
// Do not own the serial number... 'tis shared.
Chips(std::shared_ptr<SerialNumber> poSerial):m_poSerial{poSerial}{}
Chips(int shelf, SerialNumber oSerial):m_poSerial{oSerial}, m_nShelf{shelf}{}
string GetFlavour() {return m_poSerial->getFlavour()};
int GetShelf() {return m_nShelf;}
protected:
std::shared_ptr<SerialNumber> m_poSerial;
int m_nShelf;
}
// stores std::shared_ptr but you could also use one of the shared containers from boost.
Chips pringles{ chipMap.at("standard pringles - sour cream") };
This way once you have a set of SerialNumbers for your products then the product behaviour does not change. The only change is the "configuration" which is encapsulated in the SerialNumber. Means that the Chips class doesn't need to change.
Anyway, somewhere someone needs to know how to build the class. Of course you could you template based injection as well but your code would need to inject the correct type.
One last idea. If SerialNumber ctor took a string (XML or JSON for example) then you could have your program read the configurations at runtime, after they have been defined by a manager type person. This would decouple the business needs from your code, and that would be a robust way to future-proof.
Oh... and I would recommend NOT using Hungarian notation. If you change the type of an object or parameter you also have to change the name. Worse you could forget to change them and other will make incorrect assumptions. Unless you are using vim/notepad to program with then the IDE will give you that info in a clearer manner.
#user1158692 - The party instantiating Chips only needs to know about SerialNumber in one of my proposed designs, and that proposed design stipulates that the SerialNumber class acts to configure the Chips class. In that case the person using Chips SHOULD know about SerialNumber because of their intimate relationship. The intimiate relationship between the classes is exactly the reason why it should be injected via constructor. Of course it is very very simple to change this to use a setter instead if necessary, but this is something I would discourage, due to the represented relationship.
I really doubt that it is absolutely necessary to create the instances of chips without knowing the serial number. I would imagine that this is an application issue rather than one that is required by the design of the class. Also, the class is not very usable without SerialNumber and if you did allow construction of the class without SerialNumber you would either need to use a default version (requiring Chips to know how to construct one of these or using a global reference!) or you would end up polluting the class with a lot of checking.
As for you complaint regarding the shared_ptr... how on earth to you propose that the ownership semantics and responsibilities are clarified? Perhaps raw pointers would be your solution but that is dangerous and unclear. The shared_ptr clearly lets designers know that they do not own the pointer and are not responsible for it.
I have a class with a complex construction process with many parameters. Multiple clients share objects of this class, and the union of these clients parameters are used to instantiate the class. Therefore I have a factory class that stores these requirements, checks consistency of the various clients' requests, and instantiates the class.
Additionally, there are a common set of use models (or sets of parameters) which multiple clients use for multiple factories.
For instance, consider an example. (Note that the actual code is C++, but my experience is in Python so I'll pseudo-code in Python. Yes, I know that this example wouldn't actually work as-is.)
class Classroom:
def __init__(self, room_size=None, n_desks=None, n_boards=None,
n_books=None, has_globe=False, ... ):
...
class ClassroomFactory:
def __init__(self):
self._requirements = dict()
def addRequirement(self, name, value):
if name.startswith("n_"):
self._requirements[name] = max(value, self._requirements.get(name, 0))
...
def createClassroom(self):
return Classroom(**self._requirements)
# instantiate the factory
factory = ClassroomFactory()
# "client 1" is a geography teaacher
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
factory.addRequirement("has_globe", True)
# "client 2" is a math teacher
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
# "client 3" is a after-school day-care
factory.addRequirement("room_size", (20,20))
factory.addRequirement("has_carpet", True)
room = factory.createClassroom()
The common use model is as a teacher, we need 10 desks and a board. I think this is best served by a non-member function/decorator, something like:
def makeTeacherRoom(factory):
factory.addRequirement("n_desks", 10)
factory.addRequirement("n_boards", 1)
return factory
This seems like a great example of the "prefer non-member/non-friend to member" paradigm.
The thing that I'm struggling with is, within the framework of a much bigger OO code, where should these types of non-member functions/decorators live, both in terms of namespace and in terms of actual file?
Should they live in the factory's file/namespace? They are closely related to the factory, but they're limitations on the general factory, and need not be used to use the factory.
Should they live in the client's file/namespace? The client understands these use models, but this would limit re-use amongst multiple clients.
Should they live with a common base class of the clients (for instance, one could imagine a "teacher" class/namespace which would also provide the non-member function makeTeacherRoom(), which would be inherited by MathTeacher and GeographyTeacher.
Should they live somewhere else completely, in a "utils" file? And if so in which namespace?
This is primarily a personal decision. Most of your options have no technical negative effects. For example:
They could, because of locality of use, but it's not necessary.
They could, because of locality of data, but again...
They could, although this one does seem like it could make things a bit messier. Making utility classes, you may have to end up inheriting them, or making parts virtual to override later, which will get ugly pretty quick.
This is my personal favorite, or a variant of this.
I typically make a relevantly-named util file (or class with static methods) and put it in the same namespace as the classes it utilates (the more helpful version of mutilate). For a Education::Teacher class, you could have a Education::TeacherUtils file or class containing the functions that operate on Teacher. This keeps a pretty obvious naming tie-in, but also puts the util functions in their own area, so they can be included from whatever needs them (in the Teacher.cpp or similar would prevent that). In the case of a class, you can make the util and base classes friends, which is occasionally helpful (but something to use rarely, as it may be a smell).
I've seen a naming variation, Education::Utils::Teacher, but that's somewhat harder to translate to files (unless you put things into a utils dir) and can also cause name resolution oddness (in some contexts, the compiler may try to use Education::Utils::Teacher instead of Education::Teacher when you didn't mean to). Because of this, I prefer to keep utils as a suffix.
You may want to handle non-member functions in a singleton class for your application. A factory maybe executed from the program, or another object.
C++ supports global functions (non member functions), but, using a single object for the application, "does the trick".
Additionally, since the "Classroom" object may be instantiated with many optional parameters, you may want to assign it, after calling the constructor ( "init" in python ).
// filename: "classrooms.cpp"
class ClassroomClass
{
protected:
int _Room_Size;
int _N_Desks;
int _N_Boards;
int _N_Books;
bool _Has_Globe;
public:
// constructor without parameters,
// but, can be declared with them
ClassroomClass()
{
_Room_Size = 0;
_N_Desks = 0;
_N_Boards = 0;
_N_Books = 0;
_Has_Globe = false;
} // ClassroomClass()
public int get_Room_Size()
{
return _Room_Size;
}
public void set_Room_Size(int Value)
{
_Room_Size = Value;
}
// other "getters" & "setters" functions
// ...
} // class ClassroomClass
class ClassroomFactoryClass
{
public:
void addRequirement(char[] AKey, char[] AValue);
} // class ClassroomFactoryClass
class MyProgramClass
{
public:
ClassroomFactoryClass Factory;
public:
void makeTeacherRoom();
void doSomething();
} // class MyProgramClass
void MyProgramClass::addRequirement(char[] AKey, char[] AValue)
{
...
} // void MyProgramClass::addRequirement(...)
void MyProgramClass::makeTeacherRoom()
{
Factory.addRequirement("n_desks", "10")
Factory.addRequirement("n_boards", "1")
} // void MyProgramClass::makeTeacherRoom(...)
void MyProgramClass::doSomething()
{
...
} // void MyProgramClass::doSomething(...)
int main(char[][] args)
{
MyProgramClass MyProgram = new MyProgramClass();
MyProgram->doSomething();
delete MyProgram();
return 0;
} // main(...)
Cheers
Personally I would make them static members of the class.
class File
{
public:
static bool load( File & file, std::string const & fileName );
private:
std::vector< char > data;
};
int main( void )
{
std::string fileName = "foo.txt";
File myFile;
File::load( myFile, fileName );
}
With static methods they have access to the private data of the class while not belonging to a specific instance of the class. It also means the methods aren't separated from the data they act on, as would be the case if you put them in a utility header somewhere.