How to prevent a C++ compiler from creating any default class member? - c++

I'm designing some classes to access and control the peripherals of a microcontroller (adc, port, usart etc). The device have just a few (in some cases just one) instances of each peripheral, so I decided to represent each peripheral as a monostate class. The definition and usage of one of my classes would be something like this:
usart.h
class usart {
public:
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
main1.cpp
#include "usart.h"
int main()
{
usart::init();
char data;
while (true) {
data = usart::read();
usart::write(data);
}
}
But the way the usart class is defined above doesn't forbid the user from doing something like this:
main2.cpp
#include "usart.h"
int main()
{
// I don't want object construction
usart serial1;
usart serial2;
// neither assignment
serial1 = serial2;
// two objects representing the same hardware resource
// I don't want that
serial1.init();
serial2.write('r');
}
I know since C++11 I can use the delete keyword to prevent the compiler of creating default constructors and functions, but I don't know exactly what are those defaults the compiler creates. There are copy constructors, copy assigments, move semantics overloads etc. How many deletes I need to put on my class (and in what functions and constructors)?
update: I know I could (and maybe should) use namespaces instead of classes, but I'm afraid later I'll need to pass those classes (or namespaces) as template arguments. AFAIK it is not possible to use namespaces as template arguments, because of that I chose to use classes with static members instead of namespaces.

struct cannot_exist {
cannot_exist()=delete;
~cannot_exist()=delete;
cannot_exist(cannot_exist const&)=delete;
cannot_exist(cannot_exist &&)=delete;
cannot_exist& operator=(cannot_exist const&)=delete;
cannot_exist& operator=(cannot_exist &&)=delete;
};
this is a class with every member that C++ generates for you deleted explicitly. (You can do this with fewer, but I don't see the point being less explicit).
Simply inherit from cannot_exist and ... an instance of your class cannot exist, nor will it have any member function auto defined by the compiler. Attempts to call them will generate compiler errors.
However, once you have a class that cannot exist, consider using a namespace.
class usart:cannot_exist {
public:
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
vs
namespace usart {
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};

I would try these two ways
Declare a pure virtual function in the class. This makes the class pure virtual so it cannot be instantiated.
Declare the default constructor as a private member function. This way no outside class method can access the constructor.

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

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.

Add friend class after declaration

I am trying to write a named pipe server in C++. I have a class called client_pool which contains a container of the pipe's instances, and a single public member function write, which asynchronously sends data to all connected clients.
Problem is, clients have the tendency to disconnect unexpectedly. When this happens, the call to WriteFileEx fails with ERROR_NO_DATA. When that happens, i want to go to the client_pool class and tell it to close the client handle and remove it from the container. However, since WriteFileEx is so fricking hard to use, I created a helper class called write_context in an anonymous namespace.
So the end result is, that I want to call a private method in client_pool, which is declared in clients.h, from the class write_context, which is declared in clients.cpp. Something like that (details/error handling omitted):
clients.h
class client_pool {
struct implementation;
std::unique_ptr<implementation> pimpl;
public:
void write(uint8_t *data, size_t size);
};
clients.cpp
struct client_pool::implementation {
set<HANDLE> connected;
// ...
void disconnect(HANDLE victim)
{
CloseHandle(victim);
connected.erase(victim);
}
};
namespace { struct write_context {
OVERLAPPED overlapped;
client_pool *owner;
HANDLE target;
const uint8_t *buffer;
size_t total_size;
size_t written;
// ...
void next_chunk()
{
if(!WriteFileEx(/* ... */, write_context::completion_routine)) {
if(GetLastError() == ERROR_NO_DATA) {
// I want to do something like
owner->pimpl->disconnect(target);
}
}
}
static void CALLBACK completion_routine(DWORD errcode, DWORD transferred, LPOVERLAPPED overlapped)
{
auto self = reinterpret_cast<write_context*>(overlapped);
self->written += transferred;
if(errcode == ERROR_MORE_DATA) {
self->next_chunk();
} else {
delete self;
}
}
}; }
void client_pool::write(uint8_t *data, size_t size)
{
for each handle in pimpl->connected {
auto context = new write_context(this, handle, data, size);
context->next_chunk();
}
}
Obviously, the line owner->pimpl->disconnect(target); doesn't compile because pimpl is private. What can I do / what are my alternatvies?
Directly accessing pimpl->connected and write_context directly in your client_pool::write method is kinda contrary to the point of the pimpl idiom. You could probably make a case otherwise, until you run into a problem just like this.
I would just create an implementation::write method for which you can pass through the arguments and a pointer to client_pool.
I think if you use a named namespace instead of a anonymous namespace you could place this line inside the class definition:
friend void namespace_name::next_chunk()
Or there's placing all that extra stuff in the anonymous namespace as static functions inside the class. Because static methods and structs don't change the ABI, you can hide it from all other instances via a preprocessor trick.
Or there's the brutal and horrifying:
#define class struct
#define private public
#define protected public
Make write_context a friend of implementation. Pass pimpl as the owner of write_context.
Sorry, but this is not the best way to use PIMPL idiom.
PIMPL hides implementation details of it's owner and should be accessed only through its owners interface. So, if you want to call "client_pool::implementation" method than it should be moved to "client_pool" interface and its implementation should delegate work to "client_pool::implementation" class. In other case this looks like design bug.

What's a good safe way to initialise memory for types I don't yet know about?

I started thinking about this after receiving an answer for this question. This is a bit tricky to explain, but I'll do my best.
I'm building a small(ish) 2D game engine. There are certain requirements that I need to satisfy, since this engine has to "work" with existing code that others have written for a different engine. Some change to existing code is inevitable, but I want to minimise it.
Users of my engine need to define entities called "gadgets". These are basically structs containing shapes and other state variables. These "gadgets" fall into classes, e.g. they may decide to define an icon gadget or a button gadget - or whatever.
They will also define a message handler for that class of gadgets.
E.g.
typedef struct
{
shape shapelist[5];
int num_options;
}interface;
static void interface_message_handler( interface * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
....
}
}
Users have already given me the corresponding message handler function and also the number of bytes in a interface object. And they can then ask the engine to create new instances of their gadgets via IDs e.g:
engine->CreateNewGadget( interface_gadget_class_ID, welcome_interface_ID );
where interface_gadget_class_ID is the ID for that class of gadgets and welcome_interface_ID is the instance ID. At some point during CreateNewGadget I need to a) allocate memory to hold a new gadget and then call the gadget class's message handler on it, with a NEW_MSG so that it can initialize itself.
The problem is, if all I'm doing is allocating memory - that memory is uninitialized (and that means all the struct members are uninitialized - so if interface contains a vector, for example, then I'm going to get some wierd results if the message handler does anything with it ).
To avoid wierd results caused by doing stuff to unintialized memory, I really need to call a constructor for that memory as well before passing it to the gadget's message handler function.
e.g in the case of interface:
pfunc(new (memory) interface);
But my question is, if I have no knowledge of the types that users are creating, how can I do that?
// We create a typedef that refers to a function pointer
// which is a function that returns an interface pointer
typedef interface * (*GadgetFactory)(void);
// we'll actually create these functions by using this template function
// Different version of this function will produce different classes.
template<typename T>
interface * create_object()
{
return new T;
}
// This function takes care of setting everything up.
template<typename T>
void RegisterGadgetType(int gadget_type_id)
{
// Get outselves a copy of a pointer to the function that will make the object
GadgetFactory factory = create_object<T>;
// store factory somewhere
}
interface * CreateGadget(int gadget_type_id)
{
// get factory
GadgetFactory factory;
// factory will give me the actual object type I need.
return (*factory)();
}
RegisterGadgetType<S>(2);
CreateGadget(2);
as i see it, you always know because interface_gadget_class_ID defines the type to create.
you create a base c++ class: (corresponds to class interface in your example). this base class contains all of data members which are used by every interface subclass (that is, every gadget).
the base class also declares all methods common to every gadget. example: each gadget is able to receive a call handleMessage. handleMessage is pure virtual, because this method is the subclasses' role to fulfill.
then you extend/subclass to support the stuff you have to do with each gadget's specialization. at this point, you add the members and methods specific to each gadget subclass.
CreateNewGadget serves as a factory for all your subclasses, where the arguments determine which class you will create.
from there, c++ will handle construction/destruction, allocation sizes, etc..
if you're allowing plugins with their own factories in your engine, then you'll need another level, where third parties register their custom types and inherit from your base(s).
here's a simple layout of the interfaces (in non-compiled pseudo code):
namespace MONGadgets {
class t_interface {
protected:
t_interface(/* ... */);
public:
virtual ~t_interface();
/* each subclass must override handleMessage */
virtual t_result handleMessage(const t_message& message) = 0;
};
namespace InterfaceSubclasses {
class t_gadget1 : public t_interface {
public:
t_gadget1(const welcome_interface_ID& welcome);
virtual ~t_gadget1();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget1\n";
}
/* gadget1 has no specific instance variables or methods to declare */
};
class t_gadget2 : public t_interface {
public:
t_gadget2(const welcome_interface_ID& welcome);
virtual ~t_gadget2();
virtual t_result handleMessage(const t_message& message) {
std::cout << "t_gadget2\n";
}
private:
/* here is an example of a method specific to gadget2: */
void drawShape(const unsigned& idx);
private:
/* here is gadget2's unique data: */
shape shapelist[5];
int num_options;
};
namespace ClassID {
enum { Gadget1 = 1, Gadget2 = 2 };
}
}
/* replaced by virtual t_result t_interface::handleMessage(const t_message&)
- static void interface_message_handler( interface * myself, message * msg );
*/
class t_gadget_factory {
public:
t_interface* CreateNewGadget(const interface_gadget_class_ID& classID, const welcome_interface_ID& welcome) {
switch (classID) {
case InterfaceSubclasses::ClassID::Gadget1 :
return new InterfaceSubclasses::gadget1(welcome);
case InterfaceSubclasses::ClassID::Gadget2 :
return new InterfaceSubclasses::gadget2(welcome);
/* ... */
}
}
};
}
Example code (ignoring my other suggestion, about factories and virtual functions):
typedef struct
{
shape shapelist[5];
int num_options;
} interface;
static void interface_message_handler( void * myself, message * msg )
{
switch( msg->type )
{
case NEW_MSG:
{
interface *self = new (myself) interface;
interface_descriptor * desc = msg->desc;
// initialize myself with contents of this message.
...
}
break;
case OTHER_MSG:
{
interface *self = static_cast<interface*>(myself);
...
}
break;
....
}
}
Then your CreateNewGadget code does:
void *ptr = malloc(some_amount);
msg newmsg;
newmsg.type = NEW_MSG;
// other fields
some_message_handler(ptr, &msg);
// now we have an initialized object, that we can add to our tree or whatever.
The less horrible version is more like this:
struct gadgetinterface {
virtual ~gadgetinterface() {}
virtual void handle_message(msg *) = 0;
};
struct mygadget : gadgetinterface {
void handle_message(msg *m) {
// no need for NEW_MSG, just do other messages
}
};
gadgetinterface *mygadget_factory(some parameters) {
// use some parameters, either passed to constructor or afterwards
return new mygadget();
}
Then we register a pointer to mygadget_factory with the gadget manager, and CreateNewGadget does this:
gadgetinterface *some_factory(some parameters); // that's it!
Where some_factory is the function pointer that was registered, so in the case of this gadget type, it points to mygadget_factory.