"Stealth" class to enclose a variable in C++ - c++

I'm currently using two identical libraries for parsing commands received in Arduino (via TCP/IP and via Serial). All the difference is in the object type being passed to the parser.
//main.cpp
SerCmd sCmd;
EthCmd eCmd;
void setup() {
sCmd.listen("#",dumpCmd);
eCmd.listen("#",dumpCmd);
}
void loop() {
HardwareSerial SerClient = Serial.available();
EthernetClient EthClient = Server.available();
eCmd.read(SerClient);
sCmd.read(EthClient);
}
//SerCmd.h
class SerCmd {
public:
void read(HardwareSerial &dataObj);
}
//EthCmd.h
class EthCmd {
public:
void read(EthernetClient &dataObj);
}
It's obvious that:
The two objects are nearly identical, and they share lots of common methods (sCmd, eCd).
The two classes (SerCmd, EthCmd) can be replaced with a single class to reduce the sketch size.
How can I create a "stealth" class which could be passed to the read() method, while still addressing any of the two different objects underneath?
What's the common practice used in such situations?
So far, I am able to compile the below code, but cannot initialize any methods:
class Communication {};
HardwareSerial *SerClient;
Communication *Comm;
void setup() {
Comm = (Communication*) SerClient;
//Comm.begin(9600);
//Error: request for member 'print' in 'Comm',
//which is of non-class type 'Communication*'
}

Related

Scope and Usage of Nested Classes

I'm writing some code that interfaces with a GPS receiver and I'm trying to understand if the way I'm attempting to implement it is possible and if so how to do it.
The GPS communicates with an Arduino via I2C and I want to have a single object that handles all of the GPS interface commands. The basic structure is as follows:
Header File (Simplified)
//UBLOX.h
class UBLOX_INTERFACE
{
private:
const uint8_t i2cAddress;
public:
UBLOX_INTERFACE(uint8_t address);
class NMEA
{
private:
void intakeNMEA(); //This function needs access to UBLOX_INTERFACE::i2cAddress
//Other local variables and functions
};
class UBX_COMMS
{
private:
uint8_t prepAndSendPacket(uint8_t packet[], const uint16_t packetLength);
public:
UBX_COMMS(uint8_t ubxclass, uint8_t id, uint8_t length0, uint8_t length1);
};
class UBX_CFG_RATE : public UBX_COMMS
{
using UBX_COMMS::UBX_COMMS;
private:
public:
bool set(const uint16_t GNSSmeasureRate); // Sets GNSS measurement rate
void poll();
};
class UBX_CFG_RST : public UBX_COMMS
{
using UBX_COMMS::UBX_COMMS;
private:
public:
bool gnssReset(const uint8_t navBbrMask);
bool hardwareReset(const uint8_t resetMode);
};
}
CPP File (Simplified)
//UBLOX.cpp
#include "UBLOX.h"
//UBLOX_INTERFACE Class Functions
UBLOX_INTERFACE::UBLOX_INTERFACE(uint8_t address): i2cAddress(address)
{
NMEA nmea;
UBX_CFG_RATE ubxCFG_RATE(0x06, 0x08, 0, 6); //These values are permanently defined constants for each command type
UBX_CFG_RST ubxCFG_RST(0x06, 0x04, 0, 4);
}
//NMEA Class Functions
void UBLOX_INTERFACE::NMEA::intakeNMEA()
{
Wire.beginTransmission(i2cAddress); //This line has a compile error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress'
//There's a whole bunch more after this but not relevant to this question
}
//UBX_COMMS Class Functions
UBLOX_INTERFACE::UBX_COMMS::UBX_COMMS(uint8_t ubxclass, uint8_t id, uint8_t length0, uint8_t length1) : classByte(ubxclass), idByte(id), payloadLength{length0, length1}, stdPacketLength(packetLengthCalc(length0, length1)){};
uint8_t UBLOX_INTERFACE::UBX_COMMS::prepAndSendPacket(uint8_t packet[], const uint16_t packetLength)
{
calcAndInsertUBXChecksum(packet, packetLength);
Wire.beginTransmission(i2cAddress); //error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress'
Wire.write(packet, packetLength);
uint8_t errorCode = Wire.endTransmission();
return errorCode;
}
// UBX_CFG_RATE Class Functions
//definition of UBLOX_INTERFACE::UBX_CFG_PRT::setPort() and UBLOX_INTERFACE::UBX_CFG_PRT::poll()
// UBX_CFG_RST Class Functions
//definition of UBLOX_INTERFACE::UBX_CFG_RST::gnssReset() and UBLOX_INTERFACE::UBX_CFG_PRT::hardwareReset()
Example of how I want to use this
void main()
{
UBLOX_INTERFACE u;
u.ubxCFG_RST.hardwareReset();
u.ubxCFG_RATE.set(SOME SETTINGS HERE);
while(true)
{
u.nmea.intakeNMEA();
}
}
The real code I'm working with does not compile. Currently I'm getting errors in all of the subclasses where I attempt to use the UBLOX_INTERFACE::i2cAddress function: error: invalid use of non-static data member 'UBLOX_INTERFACE::i2cAddress' If I change the i2cAddress to be static, then I get a different error saying I have to use a non-static variable in the class construction. And on top of that, I'm unsure if my method of initializing the subclasses within the parent class constructor is even valid. Can anyone explain if this method is valid or what I should be doing instead?
You are trying to access i2cAddress from the class NMEA but you have defined the variable in the class UBLOX_INTERFACE.
The classes might be defined inside each other, but the instances of the classes does not have access to eachothers variable.
Alternatives would be to either make i2cAddress static, or global or to send a pointer or copy of i2cAddress or to UBLOX_INTERFACE to the class NMEA at some point.
Or depending on your code (i do understand it fully), you might want to put i2cAddress as a member variable of NMEA, that would also solve the problem.
Edit:
If you want to initialize a static member variable in the constructor, it is not possible to do it in the initializer list
//UBLOX_INTERFACE Class Functions
UBLOX_INTERFACE::UBLOX_INTERFACE(uint8_t address) // not here :
{
i2cAddress = address; // This should work
// The following variables does only exist in this function,
// I think that you might want to move these to the function body
// instead
NMEA nmea;
UBX_CFG_RATE ubxCFG_RATE(0x06, 0x08, 0, 6); //These values are permanently defined constants for each command type
UBX_CFG_RST ubxCFG_RST(0x06, 0x04, 0, 4);
}
And about if it would be possible to initialize like classes like you do: No I dont think it works like it does now. You need to add the classes as class members, and then initialize them in the initialize list like you previously did with i2cAddress.

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

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();

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

C++ object method calling methods from another class that includes it's

First of all, sorry for the title. I didn't know exactly how to give name to the situation I'm facing.
I am developing a project in C++ that will run over QNX (so answers that recur to Windows libraries are not good).
I have one class that holds and manipulates all my data, and a few other classes that are responsible for dealing with my UI.
The UI manipulating classes include my data class, and when they are initialized, they all get a pointer to the same data object (each one uses different parts of it, though). And the normal flow of the program is the UI receiving events from the user, and then making calls to the data class and updating itself, according to the data class replies. That all works just fine.
The problem is, sometimes it might happen that this data class object receives calls from other sorts of external events (let's say a call from a class responsible for communication), asking it to change some of it's values. After doing so, it would have to update the UI (thus, having to make a call to the UI classes).
The actual objects to all the classes (UI and data) are contained by the "main" class. But as the UI classes include the data class to be able to call it's methods, the data class including UI classes in order to be able to call their methods would fall into mutual inclusion.
The problem resumes, in a very simplistic way (I am just trying to give a visual example of the information flow), to something like this:
main.cpp
#include "interface.h"
#include "data.h"
Data data_;
Interface interface_;
// Initialize all data from files, etc
data_.Init();
// Call the interface that will use all of this data
interface_.Init(&data_);
while(1);
interface.h
#include "data.h"
class Interface
{
Data *data_;
void Init(Data *data);
void ReceiveEvent();
void ChangeScreen (int value);
};
interface.cpp
#include "interface.h"
void Interface::Init(Data *data)
{
// Get the pointer locally
data_ = data;
}
// Function called when a (for example) a touch screen input is triggered
void Interface::ReceiveEvent()
{
ChangeScreen(data_->IncreaseParam1());
}
void Interface::ChangeScreen (int value);
{
// Set the value on screen
}
data.h
class Data
{
int param 1;
void Init();
int IncreaseParam1();
void ReceiveExternalEvent();
};
**data.cpp"
#include "data.h"
void Data::Init()
{
// The value actually come from file, but this is enough for my example
param1 = 5;
}
int IncreaseParam1()
{
param1 += 5;
return param1;
}
// This is called from (for example) a communication class that has a
// pointer to the same object that the interface class object has
void ReceiveExternalEvent()
{
IncreaseParam1();
// NOW HERE IT WOULD HAVE TO CALL A METHOD TO UPDATE THE INTERFACE
// WITH THE NEW PARAM1 VALUE!
}
I hope I made myself clear enough.
Can someone please give me ideas on how to deal with this situation?
Thanks a lot in advance!
Both Data and Interface are singletons. You expect to only have one instance of each class in existence. So:
Class Data {
public:
static Data *instance;
Data()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Class Interface {
public:
static Interface *instance;
Interface()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Now, ReceiveExternalEvent() will simply invoke Data::instance->method() and/or Interface::instance->method(), and so on...
This is a classical singleton design pattern.
Also, you might find some additional Google food of likely interest to you: "model view controller" and "mvc".

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.