How to declare a class member that may be one of two classes - c++

I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?

You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();

Related

Going around in circles with Pure Virtual Functions

I am using a simple inheritance structure to try and simplify code structure and reduce common code usage across a number of classes.
The idea is to allow a simple linked list structure within the class to allow the entire set of instances to be iterated.
EDIT:
To elaborate, this is intended to support a bunch of classes that can be aggregated by type and then iterated by type. Hence the decision to use a linked list with a static "first member" held in the class.
The actual application is support classes for switches, buttons, lights, parsers inside an embedded platform (Arduino).
When I create 20 switch instances of cSwitch (for instance)
cSwitch cSwitchA(_pin,callback);
cSwitch cSwitchB(_pin,callback);
I can then use
loop() {
cSwitch::checkAll();
}
inside my "loop" function, rather than having to do:
void loop() {
cSwitchA::check();
cSwitchB::check();
...
}
...
extending this to other classes, I can do:
loop() {
cSwitch::checkAll();
cLight::checkAll();
cParser::checkAll();
}
all of the members are declared with pins, parameters and callback functions.
I think that the problem is not specific to Arduino, but a little more abstract in that it could probably arise in any similar scenario.
class cGroup {
public:
cGroup(){cGroup::register_instance(this);}
~cGroup();
static void register_instance(cGroup * _inst) {
cGroup pInstance=nullptr;
if (_inst->getFirstInstance()==nullptr) {
_inst->setFirstInstance(_inst);
return;
} else {
pInstance=_inst->getFirstInstance();
}
while (1) {
if (pInstance->getNextInstance() == nullptr) {
pInstance->setNextInstance(_inst);
return;
} else {
pInstance=_inst->getNextInstance();
}
}
}
static void checkAll(cGroup * firstInstance);
virtual cGroup* getFirstInstance()=0;
virtual void setFirstInstance(cGroup*)=0;
};
class cMemberA: public cGroup {
public:
cMemberA():cGroup(){}
static void checkAll() {cGroup::checkAll(cMemberA::firstInstance);}
static cGroup * _firstInstance;
cGroup* getFirstInstance() {return cMemberA::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberA::firstInstance = _firstInstance;}
};
cGroup * cMemberA::_firstInstance = nullptr;
class cMemberB: public cGroup {
... etc
};
The main need to do it this way stems from the fact that if I push the static "firstInstance" variable up into the cGroup class, it only allows for one long list containing many different types of Member classes. What I want is one list per type of Member class, meaning that I need to scope the static "firstInstance" variable into the Member class itself.
The problem I am finding is that I am going around in circles trying to figure out how to invoke getFirstInstance() and setFirstInstance from within the member class while only having a cGroup* pointer to play with.
If I have pure virtual classes inside of cGroup with cGroup * declarations, then these are not satisfied by declarations in the subclass of cMemberA * (and cMemberB *, cMemberC etc...)
declaring the "first-instance" members as "cMemberA*" leads to compilation issues (abstract class), but declaring them as cGroup* leads to an inability to invoke the required members in the cMemberA instances.
Is there another way to do this, or am I fundamentally going about this the wrong way? Please be gentle, it's been about 10 years since my last rodeo with C++ and I'm not a professional programmer.
Of course I can get around this issue by dispensing with cGroup entirely and just putting everything into cMemberA, cMemberB etc. but then that's where I was last week and as far as I recall, that's not the best way with C++ as the whole idea is to reduce code duplication.
The code you posted does have a problem, but I think it's different from the ones you mentioned.
The problem I see is that you call register_instance from the cGroup constructor, and then call virtual functions, eg. getFirstInstance() from that. Virtual calls don't work as expected at construction time (because the vtable isn't properly initialized yet). Basically you need to construct your object first, and you can call register once the object is fully constructed, in a second step.
The usual way around this would be to use a factory function instead of directly the constructors. The factory function would first create a new instance, then register that fully created instance, then return it. BUT, your factory function would need to create the instance on heap and return a pointer (if it returned by value, then it would register an instance, return a copy of it, then destruct the registered instance). Usually this isn't a problem, types with virtual functions are usually used as reference types (not value types) anyway, but in your particular embedded case that may be a problem.
Another way is to create intermediate classes between cGroup and cMemberX, eg. cMemberA: cMemberABase: cGroup. first_instance and getFirstIntsnace() etc. would be defined in cMemberABase. Then cMemberA's constructor could call cGroup::register, because by that time the vtable for cMemberABase is already constructed (but not yet for cMemberA!). In other words, when in the subclass constructor, the base subobject's virtuals can already be used, but not the virtuals defined in the subclass.
class cGroup {
protected:
cGroup(){}
public:
template <class G> static G* make() {
G* instance = new G();
cGroup::register_instance(instance);
return instance;
}
~cGroup() {}
static void register_instance(cGroup * _inst) {
cGroup* pInstance=nullptr;
if (_inst->getFirstInstance()==nullptr) {
_inst->setFirstInstance(_inst);
return;
} else {
pInstance=_inst->getFirstInstance();
}
while (1) {
if (pInstance->getNextInstance() == nullptr) {
pInstance->setNextInstance(_inst);
return;
} else {
pInstance=_inst->getNextInstance();
}
}
}
static void checkAll(cGroup * firstInstance) {
}
virtual cGroup* getFirstInstance()=0;
virtual void setFirstInstance(cGroup*)=0;
cGroup* getNextInstance() { return nextInstance; }
void setNextInstance(cGroup* nextInstance) { this->nextInstance = nextInstance; }
cGroup* nextInstance = nullptr;
};
class cMemberABase: public cGroup {
protected:
friend class cGroup;
cMemberABase():cGroup(){}
public:
static void checkAll() {cGroup::checkAll(cMemberABase::firstInstance);}
static cGroup * firstInstance;
cGroup* getFirstInstance() {return cMemberABase::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberABase::firstInstance = _firstInstance;}
};
cGroup* cMemberABase::firstInstance = nullptr;
class cMemberBBase: public cGroup {
protected:
friend class cGroup;
cMemberBBase():cGroup(){}
public:
static void checkAll() {cGroup::checkAll(cMemberBBase::firstInstance);}
static cGroup * firstInstance;
cGroup* getFirstInstance() {return cMemberBBase::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberBBase::firstInstance = _firstInstance;}
};
cGroup* cMemberBBase::firstInstance = nullptr;
class cMemberA: cMemberABase {
public:
cMemberA(): cMemberABase() {
cGroup::register_instance(this);
}
};
class cMemberB: cMemberBBase {
public:
cMemberB(): cMemberBBase() {
cGroup::register_instance(this);
}
};
It is much simpler and idiomatic to let the outer code organize objects into containers as needed:
cSwitch cSwitches[2] = {{_pin,callback}, {_pin,callback}};
loop() {
for (auto& switch : cSwitches)
switch.check();
}
If you want "names" for the elements, add an enum:
enum cSwitchNames { A, B, count };
cSwitches[A].check(); // if you need to check just one

return a Type, or how to preserve a type of an object pointer?

I have a very complicated code structure, but the important bits are:
typical setup: I have a base class and two classes that derive from this base class and each has own members, and which don't have a standard constructor
class BaseSolver{
...
};
class SolverA : BaseSolver{
public:
std::string a;
SolverA(TypeA objectA);
};
class SolverB : BaseSolver{
public:
int b;
SolverB(TypeB objectB);
};
Now I have a config xml file from which I read whether I have to use SolverA or SolverB. Therefore I have an IOService:
template<class T>
class IOService
{
BaseSolver* getSolver()
{
std::string variableThatIReadFromXML;
/* here I have to perform many actions before I can create a solver object
* to retrieve the data needed for the constructors */
TypeA variableIConstrucedWithDataFromXML;
TypeB anotherVariableIConstrucedWithDataFromXML;
if (variableThatIReadFromXML == "a")
return new SolverA(variableIConstrucedWithDataFromXML); // I know that this can leak memory
else if (variableThatIReadFromXML == "b")
return new SolverB(anotherVariableIConstrucedWithDataFromXML);
}
};
And somewhere in my application (for simplicity let's say it's the main.cpp):
int main(){
IOService ioService;
BaseSolver* mySolver = ioService.getSolver();
}
That is absolutely fine.
But now, in the main I have to access the members of the derived classes a and b respectively.
How can I do this?
I thought of retreving only the type of the Solver from the IOService:
class IOService
{
decltype getSolverType()
{
std::string variableThatIReadFromXML;
/* here I have to perform many actions before I can create a solver object
* to retrieve the data needed for the constructors */
TypeA variableIConstrucedWithDataFromXML;
TypeB anotherVariableIConstrucedWithDataFromXML;
if (variableThatIReadFromXML == "a")
return new SolverA(variableIConstrucedWithDataFromXML); // I know that this can leak memory
else if (variableThatIReadFromXML == "b")
return new SolverB(anotherVariableIConstrucedWithDataFromXML);
}
TypeA getConstructorDataForSolverA()
{
/* here I have to perform many actions before I can create a solver object
* to retrieve the data needed for the constructors */
return variableIConstrucedWithDataFromXML;
}
TypeB getConstructorDataForSolverB()
{
/* here I have to perform many actions before I can create a solver object
* to retrieve the data needed for the constructors */
return anotherVariableIConstrucedWithDataFromXML;
}
};
But of course I can't specify decltype as return value.
I'm really helpless. I would appreciate any hint into the right direction, or even a solution for this problem.
[Edit]: The derived solver classes need more than only the information from the xml file to work properly. That means, that I have to set some more properties which come from a mesh file. So I could give the meshfile to the IOService, so that the IOService could set the appropriate members this way:
class IOService
{
BaseSolver* getSolver(MeshType myMesh)
{
std::string variableThatIReadFromXML;
/* here I have to perform many actions before I can create a solver object
* to retrieve the data needed for the constructors */
TypeA variableIConstrucedWithDataFromXML;
TypeB anotherVariableIConstrucedWithDataFromXML;
if (variableThatIReadFromXML == "a")
{
auto solverA = new SolverA(variableIConstrucedWithDataFromXML); // I know that this can leak memory
solverA.a = mesh.a;
}
else if (variableThatIReadFromXML == "b")
{
auto solverB = new SolverB(anotherVariableIConstrucedWithDataFromXML);
solverB.b = mesh.b;
}
}
};
But then the IOService needs to know the class MeshType, what I want to avoid, because I think that it breaks encapsulation.
So I wanted to set the member a and b, respectively, in another part of my program (here for simplicity in the main).
Taking this into account, only the answer from Daniel Daranas seems like a solution for me. But I wanted to avoid dynamic casts.
So a reformulated question could be: How should I change my design to ensure encapsulation and avoid dynamic casts? [/Edit]
I am using clang 3.4 ob ubuntu 12.04 lts.
Use dynamic_cast to try to cast a pointer-to-base-class to pointer-to-derived-class. It will return NULL if the pointed-to object of the base class does not exist (NULL value of the base pointer), or is not actually a derived class object. If the result, instead, is not NULL, you have a valid pointer-to-derived-class.
int main(){
IOService ioService;
BaseSolver* mySolver = ioService.getSolver();
SolverB* bSolver = dynamic_cast<SolverB*>(mySolver);
if (bSolver != NULL)
{
int finallyIGotB = bSolver->b;
cout << finallyIGotB;
}
}
Note that there may be some better design solutions than using dynamic_cast. But at least this is one possibility.
The funny thing about polymorphism is that it points out to you when you are not using it.
Inheriting a base class in the way you are serves 1 purpose: to expose a uniform interface for objects with different behaviors. Basically, you want the child classes to look the same. If I have classes B and C that inherit from A, I want to say "do foo" to the class, and it'll do foob or fooc.
Essentially, you're flipping it around: I have a B and C of type A, and if it is B i want to do foob and if it is C I want to do fooc. While this may seem scary, usually the best way to solve the problem is to rephrase the question.
So to your example, you are currently saying "OK, so I have an XML file, and I will read data from it one way if I'm making an A, or another way if I'm making a B." But the polymorphic way would be "I have an XML file. It tells me to make an A or a B, and then I tell the instance to parse the XML file".
So one of the ways to solve this to change your solver interface:
class BaseSolver
{
public:
virtual void ReadXMLFile(string xml) = 0;
...
};
While this does rephrase the problem in a way that uses polymorphism, and removes the need for you to see what you've created, you probably don't like that for the same reason I don't: you'd have to supply a default constructor, which leaves the class in an unknown state.
So rather than enforce it at the interface level, you could enforce it at the constructor level, and make both SolverA and SolverB have to take in the XML string as part of the constructor.
But what if the XML string is bad? Then you'd get an error state in the constructor, which is also a no-no. So I'd deal with this using the factory pattern:
class SolverFactory;
class BaseSolver
{
public:
virtual void solve() = 0;
protected:
virtual int ReadXML(std::string xml) = 0;
friend class SolverFactory;
};
class A : public BaseSolver
{
public:
virtual void solve() {std::cout << "A" << std::endl;}
protected:
A(){}
virtual int ReadXML(std::string xml) {return 0;}
friend class SolverFactory;
};
class B : public BaseSolver
{
public:
virtual void solve() {std::cout << "B" << std::endl;}
protected:
B(){}
virtual int ReadXML(std::string xml) {return 0;}
friend class SolverFactory;
};
class SolverFactory
{
public:
static BaseSolver* MakeSolver(std::string xml)
{
BaseSolver* ret = NULL;
if (xml=="A")
{
ret = new A();
}
else if (xml=="B")
{
ret = new B();
}
else
{
return ret;
}
int err = ret->ReadXML(xml);
if (err)
{
delete ret;
ret = NULL;
}
return ret;
}
};
I didn't put any actual XML processing in here because I am lazy, but you could have the factory get the type from the main tag and then pass the rest of the node in. This method ensures great encapsulation, can catch errors in the xml file, and safely separates the behaviors you are trying to get. It also only exposes the dangerous functions (the default constructor and ReadXMLFile) to the SolverFactory, where you (supposedly) know what you are doing.
Edit: in response to the question
The problem you've stated is "I have a B and C of type A, and if is B i want to set "b" settings and if it is C i want to set "c" settings".
Taking advantage of polymorphism, you say "I have a B and C of type A. I tell them to get their settings."
There a couple of ways to do this. If you don't mind mangling your IO with the class, you can simply expose the method:
class BaseSolver
{
public:
virtual void GetSettingsFromCommandLine() = 0;
};
And then create the individual methods for each class.
If you do want to create them separate, then what you want is polymorphism in the io. So expose it that way:
class PolymorphicIO
{
public:
virtual const BaseSolver& get_base_solver() const = 0;
virtual void DoSettingIO() = 0;
};
an example implmentation
class BaseSolverBIO : PolymorphicIO
{
public:
virtual const BaseSolver& get_base_solver() const {return b;}
virtual void DoSettingIO() { char setting = get_char(); b.set_b(setting);}
private:
BaseSolverB b;
};
At first glance this seems like a lot of code (we've doubled the number of classes, and probably need to supply a factory class for both BaseSolver and the IO interface). Why do it?
It is the issue of scaleability/maintainability. Lets say you have figured out a new solver you want to add (D). If you are using dynamic cast, you have to find all the places in your top level and add a new case statement. If there is only 1 place, then this is pretty easy, but if it is 10 places, you could easily forget one and it would be hard to track down. Instead, with this method you have a separate class that has all the specific IO functionality for the solver.
Lets also think of what happens to those dynamic_cast checks as the number of solvers grows. You've been maintaining this software for years now with a large team, and lets say you've come up with solvers up to the letter Z. Each of those if-else statements are hundreds-a tousand of lines long now: if you have an error in O you have to scroll through A-M just to find the bug. Also, the overhead for using the polymorphism is constant, while reflection just grows and grows and grows.
The final benefit for doing it this way is if you have a class BB : public B. You probably have all the old settings from B, and want to keep them, just make it a little bigger. Using this model, you can extend the IO class as well for the io for BB and reuse that code.
One way to achieve this is to add an interface method into the base class:
class BaseSolver{
virtual void SolverMethodToCallFromMain() = 0;
...
};
class SolverA : BaseSolver{
public:
std::string a;
SolverA(TypeA objectA);
virtual void SolverMethodToCallFromMain() {/*SolverA stuff here*/};
};
class SolverB : BaseSolver{
public:
int b;
SolverB(TypeB objectB);
virtual void SolverMethodToCallFromMain() {/*SolverB stuff here*/};
};
And in main:
int main(){
IOService ioService;
BaseSolver* mySolver = ioService.getSolver();
mySolver->SolverMethodToCallFromMain();
}

How to allow global functions access to private members

How do I allow global functions to have access to private members?
The constraints are that you are not allowed to directly friend the global function in the class declaration. The reason is because I do not want the users to have to see all of these global functions in the header file. The functions themselves are defined in implementation files, and I'd like to keep them hidden there as best as possible.
Now you're probably wondering why I have so many of these global functions. To keep it simple, I'm registering various WNDPROC functions with windows as callbacks, and they must be global. Furthermore, they must be able to update information that is otherwise private to various classes.
I have come up with 2 solutions, but both are a bit sticky.
Solution 1. Make all of the members that need back doors protected rather than private. In the implementation file, declare a class changer that inherits from the original class but provides public getters to protected members. When you need protected members, you can simply cast to the changer class:
//Device.h
class Device{
protected:
std::map<int,int> somethingPrivate;
};
//Device.cpp
DeviceChanger : public Device{
private:
DeviceChanger(){} //these are not allowed to actually be constructed
public:
inline std::map<int,int>& getMap(){ return somethingPrivate; }
};
void foo(Device* pDevice){ ((DeviceChanger*)pDevice)->getMap(); }
Of course, users that inherit this class now have access to the protected variables, but it allows me to at least hide most of the important private variables because they can stay private.
This works because DeviceChanger instances have the exact same memory structure as Device, so there aren't any segfaults. Of course, this is creeping into undefined C++ domain since that assumption is compiler dependent, but all compilers that I care about (MSVC and GCC) will not change the memory footprint of each instance unless a new member variable has been added.
Solution 2. In the header file, declare a friend changer class. In the implementation file, define that friend class and use it to grab private members via static functions.
//Device.h
class DeviceChanger;
class Device{
friend DeviceChanger;
private:
std::map<int,int> somethingPrivate;
};
//Device.cpp
class DeviceChanger{
public:
static inline std::map<int,int>& getMap(Device* pDevice){ return pDevice->somethingPrivate; }
};
void foo(Device* pDevice){ DeviceChanger::getMap(pDevice); }
While this does add a friend to all my classes (which is annoying), it is only one friend which can then forward the information to any global functions that need it. Of course, the users could simply define their own DeviceChanger class and freely change any of the private variables themselves now.
Is there a more accepted way to achieve what I want? I realize I'm trying to sneak around C++ class protections, but I really do not want to friend every global function in every class that needs its private members accessed; it is ugly in the header files and not easy enough to add/remove more functions.
EDIT: Using a mixture of Lake and Joel's answers, I came up with an idea that does exactly what I wanted, however it makes the implementations very dirty. Basically, you define a class with various public/private interfaces, but it's actual data is stored as a pointer to a struct. The struct is defined in the cpp file, and therefore all of it's members are public to anything in that cpp file. Even if users define their own version, only the version in the implementation files will be used.
//Device.h
struct _DeviceData;
class Device {
private:
_DeviceData* dd;
public:
//there are ways around needing this function, however including
//this makes the example far more simple.
//Users can't do anything with this because they don't know what a _DeviceData is.
_DeviceData& _getdd(){ return *dd; }
void api();
};
//Device.cpp
struct _DeviceData* { bool member; };
void foo(Device* pDevice){ pDevice->_getdd().member = true; }
This basically means that each instance of Device is completely empty except for a pointer to some data block, but it lays an interface over accessing the data that the user can use. Of course, the interface is completely implemented in the cpp files.
Additionally, this makes the data so private that not even the user can see the member names and types, but you can still use them in the implementation file freely. Finally, you can inherit from Device and get all of the functionality because the constructor in the implementation file will create a _DeviceData and assign it to the pointer, which gives you all of the api() power. You do have to be more careful about move/copy operations, as well as memory leaks though.
Lake gave me the base of the idea, so I give him credit. Thank you sir!
I usually solve this problem by extracting the application programmer interface in the form of abstract classes, which is the set of types and operations that the application programmer (i.e. the user of your library) will be able to use.
Then, in my implementation, I declare public all methods and types that will be used within my package by other classes.
For example:
API: IDevice.h
Internal: Device.h Device.cpp
I define the API classes in a way similar to:
class IDevice {
public:
// What the api user can do with the device
virtual void useMe() = 0;
};
Then, in my library (not exposed to user interface):
class Device : public IDevice {
public:
void useMe(); // Implementation
void hiddenToUser(); // Method to use from other classes, but hidden to the user
}
Then, for every header(interface) that is part of the API, i will use the IDevice type instead of the Device type, and when internally i will have to use the Device class, i will just cast the pointer down to Device.
Let's say you need a Screen class that uses the class Device, but is completely hidden to the user (and won't therefore have any API abstract class to implement):
#include "Device.h"
class Screen {
void doSomethingWithADevice( Device* device );
}
// Screen.cpp
void Screen::doSomethingWithADevice( Device* device ){
device->hiddenToUser();
}
This way, you don't have to make something private just because you don't want the user to see/use it. You obtain a further layer of abstraction (1 above public) which I call API. You will have:
API // Method/Type visible to the application programmer
public // Method/Type visible to your whole library package, but NOT to the api user
protected // Method/Type visible only to subclasses of the class where it is defined
private // Method/Type local to the defining class
Therefore, you can declare public methods you need to register as callback method, without the user seeing them.
Finally, I deliver the content of API to the user together with the binary, so that the user will have access exactly to what i explicitly defined in the API and nothing else.
You may be asking a specific coding question, but I'd like to take a step back and examine the reason why you'd want to do this, and the solutions to that.
Breaking abstraction
Are you making a decision based on private state?
class Kettle {
private:
int temperatureC;
public:
void SwitchOff();
};
void SwitchOffKettleIfBoiling(Kettle& k) {
if (k.temperatureC > 100) { // need to examine Kettle private state
k.SwitchOff();
}
}
This is relatively bad because the abstraction of Kettle now leaks outside into the SwitchOffKettleIfBoiling function, in the form of coupling to the private temperatureC. This is a bit better:
class Kettle {
private:
int temperatureC;
public:
void SwitchOffIfBoiling() {
if (temperatureC > 100) {
SwitchOff();
}
}
};
void SwitchOffKettleIfBoiling(Kettle& k) {
k.SwitchOffIfBoiling();
}
This practice is called Tell, don't Ask.
Multiple responsibilities
Sometimes you have data that is clearly related but used in different roles. Look at this example:
class Car {
private:
int statusFactor;
public:
void Drive();
};
void DriveSomewhere(Car& c) {
c.Drive();
// ...
}
void ShowOffSomething(const Car &c) {
// How can we access statusFactor, without also exposing it to DriveSomewhere?
}
One way to deal with this is to use interfaces which represent those responsibilities.
class IVehicle {
public:
virtual void Drive() = 0;
};
class IStatusSymbol {
public:
virtual int GetStatusFactor() const = 0;
};
class Car : public IVehicle, public IStatusSymbol {
// ...
};
void DriveSomewhere(IVehicle& v) {
v.Drive();
// ...
}
void ShowOffSomething(const IStatusSymbol &s) {
int status = s.GetStatusFactor();
// ...
}
This pattern is called the Facade pattern. It's useful for maintaining good abstraction without limiting your implementation.
Here's a (very) rough example of pimpl.
//Device.h
class DeviceImpl;
class Device {
public:
Device();
private:
std::unique_ptr<DeviceImpl> pimpl;
};
//Device.cpp
class DeviceImpl {
public:
friend LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
private:
std::map<int,int> somethingPrivate;
};
Device::Device()
: pimpl(new DeviceImpl)
{
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
DeviceImpl* pimpl = reinterpret_cast<DeviceImpl*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
use(pimpl->somethingPrivate);
// omitting the SetWindowLongPtr that you have to do before calling GetWindowLongPtr,
// but the concept is the same - you'd probably do it in WM_CREATE
}
Now you're probably wondering why I have so many of these global
functions. To keep it simple, I'm registering various WNDPROC
functions with windows as callbacks, and they must be global.
Furthermore, they must be able to update information that is otherwise
private to various classes.
You can use static member functions to do this instead of global functions. Then you can get at the private members just fine. The code would look a bit like this.
class MyClass {
private:
std::string some_data;
static void onEvent( void * user_data );
};
void MyClass::onEvent( void * user_data ) {
MyClass* obj = (MyClass*)(user_data);
std::cout<<some_data<<std::endl;
};
...
register_callback( &MyClass::onEvent, &myClassInstance);
The only issue is then the exposing of the onEvent function name. The solution to that is to extract an interface so that none of your private data or functions are exposed (as IMO leaking the private implementation is about as bad as leaking the names of private functions.)
// Header File.
class IMyClass {
//...
// public stuff goes here
//...
};
// Implementation file.
class MyClass : public IMyClass {
private:
std::string some_data;
static void onEvent( void * user_data );
};
void MyClass::onEvent( void * user_data ) {
MyClass* obj = (MyClass*)(user_data);
std::cout<<some_data<<std::endl;
};
...
register_callback( &MyClass::onEvent, &myClassInstance);
EDIT: Based on some of the responses to other answers it looks like a viable solution would look more like this.
// IUSBDeviceBackend.h (private)
class IUSBDeviceBackend {
public:
virtual void update(USBUpdateData data)=0;
virtual bool resondsTo(USBUpdateCode code)=0
virtual ~IUSBDeviveBackend() {}
};
// IUSBDeviceUI.h (public)
class IUSBDeviceUI {
public:
virtual void showit()=0;
};
// MyDevice.h & MyDevice.cpp (both private)
class MyDevice : public IUSBDeviceBackend, public IUSBDeviceUI {
void update(USBUpdateData data) { dataMap[data.key]=data.value; }
bool resondsTo(USBUpdateCode code) { return code==7; }
void showit(){ ... }
};
// main.cpp
main() {
std::vector<IUSBDeviceBackedn*> registry;
MyDevice dev;
registry.push_back(this);
set_user_data(&registry);
// ...
}
void mycallback(void* user_daya) {
std::vector<IUSBDeviceBackedn>* devices = reinterpret_cast<std::vector<IUSBDeviceBackedn>*>(user_data);
for(unsigned int i=0; i<devices->size(); ++i) {
if( (*devices)[i]->resondsTo( data.code ) ) { (*devices)[i]->update(data); }
}
}
Why not use factory methods to return an interface to your internal class, but still give the globals access to those internal classes? Example:
// IDriver.h public interface:
class IDriver {
public:
virtual int getFoo() = 0;
// ... other public interface methods.
// The implementation of this method will contain code to return a Driver:
static IDriver* getDriver();
};
// Driver.h internal interface (available to WNDPROC functions):
class Driver : public IDriver {
public:
int getFoo(); // Must provide this in the real Driver.
void setFoo(int aFoo); // Provide internal methods that are not in the public interface,
// but still available to your WNDPROC functions
}
// In Driver.cc
IDriver* IDriver::getDriver() { return new Driver(); }
Using this approach, IDriver.h would be a well-known public header, but you would only use Driver.h internally in your own code. This approach is well known and used my many existing C+ libraries (such as Java's JNI) to allow access to native low-level bits of your classes, without exposing it to users.

Dealing with functions in a class that should be broken down into functions for clarity?

How is this situation usually dealt with. For example, an object may need to do very specific things:
class Human
{
public:
void eat(Food food);
void drink(Liquid liquid);
String talkTo(Human human);
}
Say that this is what this class is supposed to do, but to actually do these might result in functions that are well over 10,000 lines. So you would break them down. The problem is, many of those helper functions should not be called by anything other than the function they are serving. This makes the code confusing in a way. For example, chew(Food food); would be called by eat() but should not be called by a user of the class and probably should not be called anywhere else.
How are these cases dealt with generally. I was looking at some classes from a real video game that looked like this:
class CHeli (7 variables, 19 functions)
Variables list
CatalinaHasBeenShotDown
CatalinaHeliOn
NumScriptHelis
NumRandomHelis
TestForNewRandomHelisTimer
ScriptHeliOn
pHelis
Functions list
FindPointerToCatalinasHeli (void)
GenerateHeli (b)
CatalinaTakeOff (void)
ActivateHeli (b)
MakeCatalinaHeliFlyAway (void)
HasCatalinaBeenShotDown (void)
InitHelis (void)
UpdateHelis (void)
TestRocketCollision (P7CVector)
TestBulletCollision (P7CVectorP7CVectorP7CVector)
SpecialHeliPreRender (void)
SpawnFlyingComponent (i)
StartCatalinaFlyBy (void)
RemoveCatalinaHeli (void)
Render (void)
SetModelIndex (Ui)
PreRenderAlways (void)
ProcessControl (void)
PreRender (void)
All of these look like fairly high level functions, which mean their source code must be pretty lengthy. What is good about this is that at a glance it is very clear what this class can do and the class looks easy to use. However, the code for these functions might be quite large.
What should a programmer do in these cases; what is proper practice for these types of situations.
For example, chew(Food food); would be called by eat() but should not be called by a user of the class and probably should not be called anywhere else.
Then either make chew a private or protected member function, or a freestanding function in an anonymous namespace inside the eat implementation module:
// eat.cc
// details of digestion
namespace {
void chew(Human &subject, Food &food)
{
while (!food.mushy())
subject.move_jaws();
}
}
void Human::eat(Food &food)
{
chew(*this, food);
swallow(*this, food);
}
The benefits of this approach compared to private member functions is that the implementation of eat can be changed without the header changing (requiring recompilation of client code). The drawback is that the function cannot be called by any function outside of its module, so it can't be shared by multiple member functions unless they share an implementation file, and that it can't access private parts of the class directly.
The drawback compared to protected member functions is that derived classes can't call chew directly.
The implementation of one member function is allowed to be split in whatever way you want.
A popular option is to use private member functions:
struct Human
{
void eat();
private:
void chew(...);
void eat_spinach();
...
};
or to use the Pimpl idiom:
struct Human
{
void eat();
private:
struct impl;
std::unique_ptr<impl> p_impl;
};
struct Human::impl { ... };
However, as soon as the complexity of eat goes up, you surely don't want a collection of private methods accumulating (be it inside a Pimpl class or inside a private section).
So you want to break down the behavior. You can use classes:
struct SpinachEater
{
void eat_spinach();
private:
// Helpers for eating spinach
};
...
void Human::eat(Aliment* e)
{
if (e->isSpinach()) // Use your favorite dispatch method here
// Factories, or some sort of polymorphism
// are possible ideas.
{
SpinachEater eater;
eater.eat_spinach();
}
...
}
with the basic principles:
Keep it simple
One class one responsibility
Never duplicate code
Edit: A slightly better illustration, showing a possible split into classes:
struct Aliment;
struct Human
{
void eat(Aliment* e);
private:
void process(Aliment* e);
void chew();
void swallow();
void throw_up();
};
// Everything below is in an implementation file
// As the code grows, it can of course be split into several
// implementation files.
struct AlimentProcessor
{
virtual ~AlimentProcessor() {}
virtual process() {}
};
struct VegetableProcessor : AlimentProcessor
{
private:
virtual process() { std::cout << "Eeek\n"; }
};
struct MeatProcessor
{
private:
virtual process() { std::cout << "Hmmm\n"; }
};
// Use your favorite dispatch method here.
// There are many ways to escape the use of dynamic_cast,
// especially if the number of aliments is expected to grow.
std::unique_ptr<AlimentProcessor> Factory(Aliment* e)
{
typedef std::unique_ptr<AlimentProcessor> Handle;
if (dynamic_cast<Vegetable*>(e))
return Handle(new VegetableProcessor);
else if (dynamic_cast<Meat*>(e))
return Handle(new MeatProcessor);
else
return Handle(new AlimentProcessor);
};
void Human::eat(Aliment* e)
{
this->process(e);
this->chew();
if (e->isGood()) this->swallow();
else this->throw_up();
}
void Human::process(Aliment* e)
{
Factory(e)->process();
}
One possibility is to (perhaps privately) compose the Human of smaller objects that each do a smaller part of the work. So, you might have a Stomach object. Human::eat(Food food) would delegate to this->stomach.digest(food), returning a DigestedFood object, which the Human::eat(Food food) function processed further.
Function decomposition is something that is learnt from experience, and it usually implies type decomposition at the same time. If your functions become too large there are different things that can be done, which is best for a particular case depends on the problem at hand.
separate functionality into private functions
This makes more sense when the functions have to access quite a bit of state from the object, and if they can be used as building blocks for one or more of the public functions
decompose the class into different subclasses that have different responsibilities
In some cases a part of the work falls naturally into its own little subproblem, then the higher level functions can be implemented in terms of calls to the internal subobjects (usually members of the type).
Because the domain that you are trying to model can be interpreted in quite a number of different ways I fear trying to provide a sensible breakdown, but you could imagine that you had a mouth subobject in Human that you could use to ingest food or drink. Inside the mouth subobject you could have functions open, chew, swallow...

Optional Member Objects

Okay, so you have a load of methods sprinkled around your system's main class. So you do the right thing and refactor by creating a new class and perform move method(s) into a new class. The new class has a single responsibility and all is right with the world again:
class Feature
{
public:
Feature(){};
void doSomething();
void doSomething1();
void doSomething2();
};
So now your original class has a member variable of type object:
Feature _feature;
Which you will call in the main class. Now if you do this many times, you will have many member-objects in your main class.
Now these features may or not be required based on configuration so in a way it's costly having all these objects that may or not be needed.
Can anyone suggest a way of improving this?
EDIT: Based on suggestion to use The Null Object Design Pattern I've come up with this:
An Abstract Class Defining the Interface of the Feature:
class IFeature
{
public:
virtual void doSomething()=0;
virtual void doSomething1()=0;
virtual void doSomething2()=0;
virtual ~IFeature(){}
};
I then define two classes which implement the interface, one real implementation and one Null Object:
class RealFeature:public IFeature
{
public:
RealFeature(){};
void doSomething(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething1(){std::cout<<"RealFeature doSomething()"<<std::endl;}
void doSomething2(){std::cout<<"RealFeature doSomething()"<<std::endl;}
};
class NullFeature:public IFeature
{
public:
NullFeature(){};
void doSomething(){std::cout<<"NULL doSomething()"<<std::endl;};
void doSomething1(){std::cout<<"NULL doSomething1()"<<std::endl;};
void doSomething2(){std::cout<<"NULL doSomething2()"<<std::endl;};
};
I then define a Proxy class which will delegate to either the real object or the null object depending on configuration:
class Feature:public IFeature
{
public:
Feature();
~Feature();
void doSomething();
void doSomething1();
void doSomething2();
private:
std::auto_ptr<IFeature> _feature;
};
Implementation:
Feature::Feature()
{
std::cout<<"Feature() CTOR"<<std::endl;
if(configuration::isEnabled() )
{
_feature = auto_ptr<IFeature>( new RealFeature() );
}
else
{
_feature = auto_ptr<IFeature>( new NullFeature() );
}
}
void Feature::doSomething()
{
_feature->doSomething();
}
//And so one for each of the implementation methods
I then use the proxy class in my main class (or wherever it's required):
Feature _feature;
_feature.doSomething();
If a feature is missing and the correct thing to do is ignore that fact and do nothing, you can get rid of your checks by using the Null Object pattern:
class MainThing {
IFeature _feature;
void DoStuff() {
_feature.Method1();
_feature.Method2();
}
interface IFeature {
void Method1();
void Method2();
}
class SomeFeature { /* ... */ }
class NullFeature {
void Method1() { /* do nothing */ }
void Method2() { /* do nothing */ }
}
Now, in MainThing, if the optional feature isn't there, you give it a reference to a NullFeature instead of an actual null reference. That way, MainThing can always safely assume that _feature isn't null.
An auto_ptr by itself won't buy you much. But having a pointer to an object that you lazily load only when and if you need it might. Something like:
class Foo {
private:
Feature* _feature;
public:
Foo() : _feature(NULL) {}
Feature* getFeature() {
if (! _feature) {
_feature = new Feature();
}
return _feature;
}
};
Now you can wrap that Feature* in a smart pointer if you want help with the memory management. But the key isn't in the memory management, it's the lazy creation. The advantage to this instead of selectively configuring what you want to go create during startup is that you don't have to configure – you simply pay as you go. Sometimes that's all you need.
Note that a downside to this particular implementation is that the creation now takes place the first time the client invokes what they think is just a getter. If creation of the object is time-consuming, this could be a bit of a shock to, or even a problem for, to your client. It also makes the getter non-const, which could also be a problem. Finally, it assumes you have everything you need to create the object on demand, which could be a problem for objects that are tricky to construct.
There is one moment in your problem description, that actually would lead to failure. You shouldn't "just return" if your feature is unavailable, you should check the availability of your feature before calling it!
Try designing that main class using different approach. Think of having some abstract descriptor of your class called FeatureMap or something like that, which actually stores available features for current class.
When you implement your FeatureMap everything goes plain and simple. Just ensure (before calling), that your class has this feature and only then call it. If you face a situation when an unsupported feature is being called, throw an exception.
Also to mention, this feature-lookup routine should be fast (I guess so) and won't impact your performance.
I'm not sure if I'm answering directly to your question (because I don't have any ideas about your problem domain and, well, better solutions are always domain-specific), but hope this will make you think in the right way.
Regarding your edit on the Null Object Pattern: If you already have a public interface / private implementation for a feature, it makes no sense to also create a null implementation, as the public interface can be your null implementation with no problems whatsoever).
Concretely, you can have:
class FeatureImpl
{
public:
void doSomething() { /*real work here*/ }
};
class Feature
{
class FeatureImpl * _impl;
public:
Feature() : _impl(0) {}
void doSomething()
{
if(_impl)
_impl->doSomething();
// else case ... here's your null object implementation :)
}
// code to (optionally) initialize the implementation left out due to laziness
};
This code only benefits from a NULL implementation if it is performance-critical (and even then, the cost of an if(_impl) is in most cases negligible).