QtScript -- script-side callback through C++-side implementation - c++

The solution may be simple. Then again it may not be possible.
I have the base callback class:
class CFCallback {
int command_;
int transfer_rate_;
public:
CFCallback(int command, int transfer_rate = 0) {
command_ = command; transfer_rate_ = transfer_rate; }
virtual ~CFCallback() {}
virtual void operator()(void *data) = 0;
int GetCommand() { return command_; }
int GetTransferRate() { return transfer_rate_; }
};
And here's one example of deriving from CFCallback:
void CFPacketVersion::InitiateVersion() {
class InitiateVersionCB : public CFCallback {
CFPacketVersion *visitor_;
public:
InitiateVersionCB(CFPacketVersion *v, int command) :
CFCallback(command) {
visitor_ = v;
}
void operator()(void *data) {
Packet *pkt = (Packet *)data;
unsigned char *pkt_data = pkt->GetData();
std::string version = "";
for(unsigned int i = 0; i < pkt->GetDataLength(); i++ )
version+= pkt_data[i];
delete []pkt_data;
boost::regex rex("CFA(.*?):h(.*?),v(.*?)$");
boost::smatch what;
if( boost::regex_match(version, what, rex) ) {
if(visitor_->GetModel()->GetName() != what[1].str() )
LCDInfo("Crystalfontz: Model mismatch");
visitor_->SetHardwareVersion(what[2]);
visitor_->SetFirmwareVersion(what[3]);
}
}
};
GetVersion(new InitiateVersionCB(this, 1));
}
GetVersion(CFCallback *) is provided to the script engine.
I want to be able to do the same thing as seen in InitiateVersion, but on the javascript side of things. Is that possible?
I know I need to register meta type info for CFCallback. But I don't know if it's possible to use a pointer to a CFCallback. What I tried initially didn't work.
Also, seeing as CFCallback is a functor, I'm not sure how I translate that over to javascript. I imagine I can make CFCallback a QObject and provide a signal emitted from operator(). If you have any tips, please share.

I'm afraid it won't work the way you've set it up.
If you want to be able to create the callback in javascript, you need a QObject with an accessible GetVersion(QScriptValue) which the script will the use to pass a script-based implementation of the callback. Note, though, that the callback will not be able to work with untyped (void*) data - you need to pass either a valid QtScript object or QObject with a proper interface (like the Packet one in your example!)
You could then wrap it up like this:
QtScript:
function mycb(packet) {
var pkt_data = packet.getData(); // pkt_data is probably a String or custom object with proper interface so to simplify things get the version as string
var version = pkt_data.toString();
pkt_data.release(); // to simulate delete [] pkt_data; this is part of custom interface
// proceed further with the regex checks
}
GetVersion(mycb); // implies that you define the GetVersion() as a property of the global object
C++:
QScriptValue getVersion(QScriptContext *ctx, QScriptEngine *engine)
{
void *data = ...;
Packet pkt_data = wrapPacketData(data);
// Packet is interface registered with QtScript or inherits QObject
// it has methods getData(), toString() and release()
QScriptValueList args;
QScriptValue pkt_data_param = engine->newQObject(&pkt_data);
args << pkt_data_param;
QScriptValue cb = ctx->argument(0);
Q_ASSERT(cb.isFunction()); // we expect a function object!
cb.call(QScriptValue(), args);
}
QScriptValue getVersionFun = engine->newFunction(getVersion);
engine->globalObject().setProperty(QLatin1String("GetVersion"), getVersionFun);

Related

Converting different classes to void* and back safely in C++

I have a map of callbacks that pass information and execute various functions throughout code, very much like events in C# but in C++.
The map is defined as
std::map<std::string, std::function<void(uint8_t*)>> mCallbacks
It is passed by reference to all subprograms
Then each class binds its callbacks as such
mCallbacks["Status_Label"] = std::bind(&MenuHandler::LabelEditCallback, this, std::placeholders::_1);
Where
bool MenuHandler::LabelEditCallback(uint8_t * m_label_data)
{
int text_size = ((int*)m_label_text)[0];
char* v_text = (char*)&m_label_text[1];
}
And each event gets called from a different subprogram like this:
if (mCallbacks.find("Status_Label") != mCallbacks.end())
mCallbacks.at("Status_Label")((uint8_t*)selected_text);
This makes it easy to pass data and events around the program without making a mess of objects and references
As you can see, this is extremely unsafe, and converting from a uint8_t pointer to various data formats can easily lead to corrupted stack.
The problem is, I don't have a specific structure for callback arguments, some of them may be sending text data, others may be sending numbers.
My solution is to define structs that will be cast to void* when calling the event, and back in the callback function
Something like this (untested):
struct Label_Callback_Data
{
Label_Callback_Data(std::string v_name, std::string v_text)
{
labelName = v_name;
labelText = v_text;
size_of = sizeof(this);
}
int size_of;
std::string labelName;
std::string labelText;
};
And I would call it like this:
if (mCallbacks.find("Status_Label") != mCallbacks.end())
mCallbacks.at("Status_Label")((uint8_t*)Label_Callback_Data("Status_Label_name", "TEXT"))
But then how would I recover it here? If I dont know the exact size of the object?
bool MenuHandler::LabelEditCallback(uint8_t * m_label_data)
{
//?? Label_Callback_Data text_size = (Label_Callback_Data*)m_label_text
}
One solution is to use object with fixed size arrays, but there has to be a C++11 solution that is safe to use, maybe something using dynamic_pointer_casts?
Also, as a bonus question, how would I know if the object passed to the callback function is smaller in size than it is expecting? Is it possible to check this and just return a false from the callback function so the program doesn't crash?
Thank you,
This code is not tested, so there may be logical mistakes I'm willing to correct per responses.
You should generally prefer to use a lambda instead of std::bind().
Try something more like this:
std::map<std::string, std::function<void(void*)>> mCallbacks;
struct Label_Callback_Data
{
std::string labelName;
std::string labelText;
Label_Callback_Data(std::string v_name, std::string v_text)
: labelName(v_name), labelText(v_text) { }
};
...
mCallbacks["Status_Label"] = [this](void *data){ this->LabelEditCallback(data); };
...
auto iter = mCallbacks.find("Status_Label");
if (iter != mCallbacks.end())
{
Label_Callback_Data data("Status_Label_name", "TEXT");
iter->second(&data);
}
...
bool MenuHandler::LabelEditCallback(void *m_label_data)
{
Label_Callback_Data *data = static_cast<Label_Callback_Data*>(m_label_text);
// use data->labelName and data->labelText as needed...
}
Alternatively, you could move the type-cast into the lambda itself, so LabelEditCallback() doesn't need to deal with void* at all:
std::map<std::string, std::function<void(void*)>> mCallbacks;
struct Label_Callback_Data
{
std::string labelName;
std::string labelText;
Label_Callback_Data(std::string v_name, std::string v_text)
: labelName(v_name), labelText(v_text) { }
};
...
mCallbacks["Status_Label"] = [this](void *data){ this->LabelEditCallback(static_cast<Label_Callback_Data*>(data)); };
...
auto iter = mCallbacks.find("Status_Label");
if (iter != mCallbacks.end())
{
Label_Callback_Data data("Status_Label_name", "TEXT");
iter->second(&data);
}
...
bool MenuHandler::LabelEditCallback(Label_Callback_Data *m_label_data)
{
// use m_label_data->labelName and m_label_data->labelText as needed...
}
This is how I did it
...
//The container
std::map<std::string, std::function<void(std::shared_ptr<CallbackData::BlankData>)>> mCallbacks
...
//CALLBACK FUNCTION
bool InputManager::KeyboardCallback(std::shared_ptr<CallbackData::BlankData> callback_data)
{
std::shared_ptr<CallbackData::Keyboard> keyboard_data = std::dynamic_pointer_cast<CallbackData::Keyboard>(callback_data);
if (keyboard_data == nullptr)
return false;
///...
}
...
//CALLBACK EVENT
if (mCallbacks.find("Keyboard") != mCallbacks.end())
{
std::shared_ptr<CallbackData::Keyboard> keyboard_data = std::make_shared<CallbackData::Keyboard>(m_keyboardState);
mCallbacks.at("Keyboard")(std::dynamic_pointer_cast<CallbackData::BlankData>(keyboard_data));
}
...
//Data structure
namespace CallbackData
{
struct BlankData
{
virtual ~BlankData() {};
};
struct Keyboard : public BlankData
{
Keyboard(uint8_t* kb_data)
{
kbData = kb_data;
}
uint8_t* kbData;
};
}

OOP in Lua From C

I would like to implement Object Orientated Programming in my lua interpreter, I understand that I can return a lua table from a C Function. And I would like the table that is returned to be full of C functions.
player = getClosestPlayer();
player.walkTo();
where both getClosestPlayer() and walkTo() are C functions.
From the C function for walkTo(), how do I differentiate between object types?
I would prefer every object to have a gid that I can use to identify it (player.gid) but how do I access that gid from the c function?
In other words, what is the equivalent of self.gid from C code?
int l_playerWalkTo(lua_State* functionState){
int gid = // self.gid?
// do something with gid
}
One way I could do this is to upvalue every single function in the table, but is there a more elegant way to do it?
Many thanks to macroland for his answer, I just though I would clear up what he has said.
This lua wrapper can be used to implement c++ classes into Lua:
https://bitbucket.org/alexames/luawrapper/overview
A great example of the usage of this library can be found here:
https://bitbucket.org/alexames/luawrapperexample/src/
Here is the code (taken straight from the example site)
Lua:
alicesaccount = BankAccount.new("Alice", 100)
alicesaccount:deposit(20);
alicesaccount:deposit(30);
alicesaccount:deposit(40);
c++:
BankAccount* BankAccount_new(lua_State *L)
{
const char* owner = luaL_checkstring(L, 1);
float balance = luaL_checknumber(L, 2);
return new BankAccount(owner, balance);
}
int BankAccount_deposit(lua_State *L)
{
BankAccount* account = luaW_check<BankAccount>(L, 1);
float amount = luaL_checknumber(L, 2);
account->deposit(amount);
return 0;
}
static luaL_Reg BankAccount_table[] =
{
{ NULL, NULL }
};
static luaL_Reg BankAccount_metatable[] =
{
{ "deposit", BankAccount_deposit },
{ NULL, NULL }
};
int luaopen_BankAccount(lua_State* L)
{
luaW_register<BankAccount>(L,
"BankAccount",
BankAccount_table,
BankAccount_metatable,
BankAccount_new // If your class has a default constructor you can omit this argument,
// LuaWrapper will generate a default allocator for you.
);
return 1;
}
As you can see, Using this method the first argument is an instance of the object
I had the similar problem and the way I resolved is:
1) Create an interface class in C++ with abstract methods
class LuaInterfaceOOP
{
public:
LuaInterfaceOOP(){}
virtual CObject* clone(void) const=0;
virtual wxString type(void)=0;
virtual wxString ToString(void)=0;
wxString GetType()return this->type();
wxString GetToString() return this->ToString();
virtual ~CObject(){}
};
2) Any class that you want to expose to Lua should implement this to be consistent.
class MyClass: public LuaInterfaceOOP
{
public:
wxString type() { return "MyClass";}
wxString ToString();
};
3) When you write a wrapper for this class make sure
int MyClass_toString(lua_State* L)
{
MyClass* mc= luaW_check<MyClass>(L, 1);
const char* str=mc->ToString().c_str();
lua_pushstring(L, str);
return 1;
}
int MyClass_type(lua_State* L)
{
lua_pushstring(L,"MyClass");
return 1;
}
4) Overload the type function provided by Lua, for you the important part will be:
case LUA_TUSERDATA:
{
wxString str1;
if(lua_getmetatable(L,idx)) // Stk: Userdata Table
{
lua_getfield(L,-1,"type"); // Stk: Userdata Table function
if(!lua_pcall(L,0,1,0)) // Stk: Userdata Table string
{
str1<<lua_tostring(L,-1);
wxReturnStr<<str1;
lua_pop(L,2);// Stk: Userdata
}
else //stk: Userdata table
{
lua_pop(L,1);
wxReturnStr<<"userdata"; //stk: Userdata
}
}else wxReturnStr<<"userdata";
break;
}
EDIT 1: Adding code to wrap C++ funcs to Lua
static luaL_Reg MyClass_table[] = {
{ NULL, NULL }
};
static luaL_Reg Myclass_metatable[] = {
{"type", Myclass_type},
{"__tostring", Myclass_toString},
{ NULL, NULL }
};
Finally,
static int luaopen_MyClass(lua_State* L)
{
luaW_register<MyClass>(L, "MyClass", MyClass_table, MyClass_metatable, MyClass_new);
return 1;
}
Now in Lua you can use an expression such as if(type(aclass)=="MyClass")
I am not sure if these steps are the best way, but so far it worked.

How can I boost::bind an abstract overriden method, so that the child's method is called?

I'm writing a base class which has an abstract callback. Like this:
class ValueListener
{
public:
ValueListener();
void registerPoint(ValuesSource &mgr, bool create=true);
void valueReceived( QVariant value ) = 0; /* slot */
QString valueName() = 0;
};
The overriding classes shall implement what do they want to do with the received value. But ValueListener itself is responsible for registering the callback:
void ValueListener::registerPoint( ValuesSource& mgr, bool create ) {
ValueSourceInfo* info = mgr.getPoint(valueName(), create);
if(info) {
// Connect the callback
info->valueChanged.connect( boost::bind( &ValueListener::valueReceived, this, _1 ) );
}
}
But obviously, neither this neither the &ValueListener::valueReceived are the things that should be receiving value updates - the overriding class should. So how can I bind the overridden method without knowing it?
Turns out doing this is probably a flawed idea. Instead, I created two methods, one normal and one private:
class ValueListener
{
public:
ValueListener();
void registerPoint(ValuesSource &mgr, bool create=true);
void valueReceived( QVariant value ) = 0;
QString valueName() = 0;
private:
void valueReceivedPrivate( QVariant value ) {valueReceived(value);}; /* slot */
};
And I used connect on the private method:
void ValueListener::registerPoint( ValuesSource& mgr, bool create ) {
ValueSourceInfo* info = mgr.getPoint(valueName(), create);
if(info) {
// Connect the callback
info->valueChanged.connect( boost::bind( &ValueListener::valueReceivedPrivate, this, _1 ) );
}

Avoid dynamic_cast with derived classes (Cast Derived class)

I am new to C++ and came to a point, where I generate an overhead with classes. I have a QTcpSocket and read messages from it and create objects, for example MessageJoin, MessagePart, MessageUserData etc. I send these objects to my client and display them (+ do some UI updating).
Now here comes my problem. I tested a few design techniques but all of them are not that nice:
Pass each parameter of a message object in a signal/slot connection to the client - small overhead but not that good-looking
Create a method for each Message-Type (messageJoinReceived, messageNoticeReceived etc.)
Create one method and use dynamic_cast to cast für each class and test it
For a better understanding, I added my dynamic_cast version. As a said, the code looks ugly and unusable. My questions are:
Is there a better way to do it with (a) dynamic_cast
Is there another way (For example a design pattern) to solve such a problem ? maybe add a method in the classes and return the type or something like this
I read about the visitor pattern. This pattern is just for dynamic object types in Getter/Setter methods ?
A few side notes
I can use RTTI
Speed isn't a big deal. Clean and understandable code is more important
I use Qt and have the possiblity to use qobject_cast and signal/slots
Here is my code (Pastebin-Link):
// Default class - contains the complete message (untouched)
class Message
{
public:
QString virtual getRawMessage() { return dataRawMessage; }
protected:
QString dataRawMessage;
};
// Join class - cointains the name of the joined user and the channel
class MessageJoin : public Message
{
public:
MessageJoin(const QString &rawmessage, const QString &channel, const QString &user)
{
dataRawMessage = rawmessage;
dataChannel = channel;
dataUser = user;
}
QString getChannel() { return dataChannel; }
QString getUser(){ return dataUser; }
private:
QString dataChannel;
QString dataUser;
};
// Notice class - contains a notification message
class MessageNotice : public Message
{
public:
MessageNotice(const QString &rawmessage, const QString &text)
{
dataRawMessage = rawmessage;
dataText = text;
}
QString getText() { return dataText;}
private:
QString dataText;
};
// Client code - print message and update UI
void Client::messageReceived(Message *message)
{
if(message)
{
MessageJoin *messagejoin;
MessagePart *messagepart;
MessageNotice *messagenotice;
if((messagejoin = dynamic_cast<MessageJoin *>(message)) != 0)
{
qDebug() << messagejoin->getUser() << " joined " << messagejoin->getChannel();
// Update UI: Add user
}
else if((messagenotice = dynamic_cast<MessageNotice *>(message)) != 0)
{
qDebug() << messagenotice->getText();
// Update UI: Display message
}
else
{
qDebug() << "Cannot cast message object";
}
delete message; // Message was allocated in the library and is not used anymore
}
}
This looks quite similar to the expression problem and AFAIK there is no way to avoid casts if you are going to add new messages and new ways to handle them. However it's not that hard to make more eye pleasing wrap for necessary run-time stuff. Just create a map from message type to corresponding handler using typeid.
#include <functional>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
typedef std::function<void(Message *)> handler_t;
typedef std::unordered_map<
std::type_index,
handler_t> handlers_map_t;
template <class T, class HandlerType>
handler_t make_handler(HandlerType handler)
{
return [=] (Message *message) { handler(static_cast<T *>(message)); };
}
template <class T, class HandlerType>
void register_handler(
handlers_map_t &handlers_map,
HandlerType handler)
{
handlers_map[typeid(T)] = make_handler<T>(handler);
}
void handle(handlers_map_t const &handlers_map, Base *message)
{
handlers_map_t::const_iterator i = handlers_map.find(typeid(*message));
if (i != handlers_map.end())
{
(i->second)(message);
}
else
{
qDebug() << "Cannot handle message object";
}
}
Then register handlers for specific message types:
handlers_map_t handlers_map;
register_handler<MessageJoin>(
handlers_map,
[] (MessageJoin *message)
{
qDebug() << message->getUser() << " joined " << message->getChannel();
// Update UI: Add user
});
register_handler<MessageNotice>(
handlers_map,
[] (MessageNotice *message)
{
qDebug() << message->getText();
// Update UI: Display message
});
And now you can handle messages:
// simple test
Message* messages[] =
{
new MessageJoin(...),
new MessageNotice(...),
new MessageNotice(...),
new MessagePart(...),
};
for (auto m: messages)
{
handle(handlers_map, m);
delete m;
}
Surely you might want to make some improvements like wrapping handlers stuff into reusable class, using QT or boost signals/slots so you can have multiple handlers for a single message, but the core idea is the same.
The visitor pattern could be a good fit i.e.
class Message
{
public:
QString virtual getRawMessage() { return dataRawMessage; }
virtual void accept(Client& visitor) = 0;
protected:
QString dataRawMessage;
};
// Join class - cointains the name of the joined user and the channel
class MessageJoin : public Message
{
public:
MessageJoin(const QString &rawmessage, const QString &channel, const QString &user)
{
dataRawMessage = rawmessage;
dataChannel = channel;
dataUser = user;
}
QString getChannel() { return dataChannel; }
QString getUser(){ return dataUser; }
void accept(Client& visitor) override
{
visitor.visit(*this);
}
private:
QString dataChannel;
QString dataUser;
};
// Notice class - contains a notification message
class MessageNotice : public Message
{
public:
MessageNotice(const QString &rawmessage, const QString &text)
{
dataRawMessage = rawmessage;
dataText = text;
}
QString getText() { return dataText;}
void accept(Client& visitor) override
{
visitor.visit(*this);
}
private:
QString dataText;
};
void Client::visit(MessageJoin& msg)
{
qDebug() << msg.getUser() << " joined " << msg.getChannel();
// Update UI: Add user
}
void Client::visit(MessageNotice& msg)
{
qDebug() << msg.getText();
// Update UI: Display message
}
// Client code - print message and update UI
void Client::messageReceived(Message *message)
{
if(message)
{
message->visit(this);
delete message; // Message was allocated in the library and is not used anymore
}
}
A better design might be to have an abstract virtual function in the Message class, called process or onReceive or similar, the sub-classes implements this function. Then in Client::messageReceived just call this function:
message->onReceive(...);
No need to for the dynamic_cast.
I would also recommend you to look into smart pointers, such as std::unique_ptr.
If you have private data in the Client class that is needed for the message processing functions, then there are many methods of solving that:
The simplest is to use a plain "getter" function in the client:
class Client
{
public:
const QList<QString>& getList() const { return listContainingUiRelatedStuff; }
// Add non-const version if you need to modify the list
};
If you just want add items to the list in your example, then add a function for that:
void addStringToList(const QString& str)
{ listContainingUiRelatedStuff.push_back(str); }
Or the non-recommended variant, make Client a friend in all message classes.
The second variant is what I recommend. For example, if you have a list of all connected clients and want to send a message to all of them, then create a function sendAll that does it.
The big idea here is to try and minimize the coupling and dependencies between your classes. The less coupling there is, the easier it will be to modify one or the other, or add new message classes, or even completely rewrite one or the other of the involved classes without it affecting the other classes. This is why we split code into interface and implementation and data hiding.

Designing Delayed Loading

I am having a hard time figuring how to design classes that can't initialize all their internal members in the constructor. I know that this should be something basic and discussed all over the net, but I'm not sure what to look for. So, for example, please consider the following code:
#include <iostream>
class Workhorse
{
public:
void SetData (const int &data)
{
this->data = data;
}
int GetData () const
{
return this->data;
}
private:
int data;
};
class Worker
{
public:
Worker ()
{
}
void Initialize (const int &data)
{
horse.SetData(data);
}
void Action () const
{
std::cout << horse.GetData() << std::endl;
}
private:
Workhorse horse;
};
int main ()
{
Worker worker;
worker.Initialize(3);
worker.Action();
return 0;
}
I want to prevent the workers from calling any methods without first calling Initialize(). The layman's implementation would be to add an isInitialized flag in the Worker class, set it to true in Initialize() and test it at the beginning of each public method (maybe also in the protected / private ones, if we introduce some inheritance?). Unfortunately, this seems a bit cumbersome and hard to maintain. Also, it's just awful to repeat an if statement in all methods. I haven't even began to ponder about thread safety issues, but, right now, I'm only implementing a single-threaded application. Is there a smarter way to design this?
EDIT: OK, I chose a dumb design as an example, which, indeed, is flawed. Let me try to give a clearer picture of what I have:
#include <iostream>
class PublicKeyCryptoProvider
{
public:
struct PublicKey
{
int shared;
};
struct PrivateKey
{
int secret;
};
int Encrypt (const int &plaintext) const
{
int ciphertext;
//apply encryption algorithm on plaintext
ciphertext = plaintext * this->pk.shared;
return ciphertext;
}
int Decrypt (const int &ciphertext) const
{
int plaintext;
//apply decryption algorithm on ciphertext
plaintext = ciphertext / this->sk.secret;
return plaintext;
}
void GenerateKeys ()
{
this->pk.shared = 4;
this->sk.secret = 4;
//generate pk and sk
}
void SetPublicKey (const PublicKey &pk)
{
this->pk = pk;
}
const PublicKey &GetPublicKey () const
{
return this->pk;
}
private:
PublicKey pk;
PrivateKey sk;
};
int main ()
{
/* scenario 1: */
PublicKeyCryptoProvider cryptoProvider;
cryptoProvider.GenerateKeys();
std::cout << cryptoProvider.Decrypt(cryptoProvider.Encrypt(3)) << std::endl;
/* /scenario 1: */
/* scenario 2: */
PublicKeyCryptoProvider cryptoProvider1;
cryptoProvider1.GenerateKeys();
PublicKeyCryptoProvider cryptoProvider2;
cryptoProvider2.SetPublicKey(cryptoProvider1.GetPublicKey());
int ciphertext = cryptoProvider2.Encrypt(3);
std::cout << cryptoProvider1.Decrypt(ciphertext) << std::endl;
//now let's do something bad...
std::cout << cryptoProvider2.Decrypt(ciphertext) << std::endl;
/* /scenario 2: */
return 0;
}
Obviously, you can imagine real life examples where scenario 2 is perfectly valid. Given the above situation, is there any better option than adding a canDecrypt flag inside the PublicKeyCryptoProvider class, which is set to true when generating keys and then tested at the beginning of the decrypt method? I have to mention that this is a very simple example, because, in my case, the PublicKeyCryptoProvider can perform faster encryptions if it is the owner of the secret key and it has much more public methods, so I would be doomed to test the flag more than a couple of times... Also, I have a client - server mockup scenario where the server exposes a bunch of public methods for the client, but the client can only call the methods after it has called the Initialize() method on the server...
I would do the following :
class Worker
{
public:
Worker (const int& data)
{
horse.SetData(data);
}
void Action () const
{
std::cout << horse.GetData() << std::endl;
}
private:
Workhorse horse;
};
Since you obviously don't want a Worker object to exist without being initialized, its initialization should be a part of its construction, and it should be instanciated without this initialization since it can't work without it.
It sounds like the behaviour you're interested in would entail having a class that acts as a manager, deciding whether to provide access to one of Workhorse's function, or a dummy function instead. One possibility would be to create an abstract parent class (Horse) specifying the interface of Workhorse, but not implementing any of the functions. Derive from it two classes, Workhorse, and TrojanHorse. TrojanHorse would implement all of the functions in the parent class as Shells, Workhorse would be as you've already created it.
The manager class could have the initialize function you're interested in, and it could store an object of type Horse. By default, the horse object could be assigned to a TrojanHorse object, but initialize would instead assign it to a Workhorse object.
This solution would avoid almost all of the speed impact from if statements, it would be maintainable in the sense that the compiler would give errors if the classes weren't changed in the proper manner, and it would still be comprehensible to another programmer looking at the code.
Great question! Its always good to make an API that is hard to use wrong, and as you are observing classes that are not fully constructed are dangerous, hard to use correctly and easy to use wrong. They set ourselves & others up for failure. I've done some refactoring on your second example to come up with a safer design that won't even allow your "do something bad" code.
The general idea was that PublicKeyCryptoProvider had too many responsibilities ( violation of SRP ):
Key generation
Key storage
Encryption
Decryption
Each one of the responsibilities has been delegated out. Now the PublicKeyCryptoProvider is more responsible for giving you the tools necessary to do encryption/decryption & key management.
#include <iostream>
#include <utility>
struct PublicKey
{
int shared;
};
struct PrivateKey
{
int secret;
};
struct KeyPair
{
PublicKey public_key;
PrivateKey private_key;
};
struct Encryptor
{
Encryptor( PublicKey shared_ )
: shared( shared_ )
{}
int Encrypt (const int &plaintext) const
{
int ciphertext;
//apply encryption algorithm on plaintext
ciphertext = plaintext * shared.shared;
return ciphertext;
}
private:
PublicKey shared;
};
struct Decryptor
{
Decryptor( PrivateKey secret_ )
: secret( secret_ )
{}
int Decrypt (const int &ciphertext) const
{
int plaintext;
//apply decryption algorithm on ciphertext
plaintext = ciphertext / secret.secret;
return plaintext;
}
private:
PrivateKey secret;
};
class PublicKeyCryptoProvider
{
public:
KeyPair GenerateKeys()
{
KeyPair keys;
//generate pk and sk
keys.public_key.shared = 4;
keys.private_key.secret = 4;
return keys;
}
Decryptor BuildDecryptor( PrivateKey key )
{
return Decryptor( key );
}
Encryptor BuildEncryptor( PublicKey key )
{
return Encryptor( key );
}
/* These are replaced by directly building an Encryptor/Decryptor
when you have a public or private key.
void SetPublicKey (const PublicKey &pk)
{
this->pk = pk;
}
const PublicKey &GetPublicKey () const
{
return this->pk;
}
*/
};
int main ()
{
/* scenario 1: */
PublicKeyCryptoProvider cryptoProvider;
auto keys = cryptoProvider.GenerateKeys();
auto decryptor = cryptoProvider.BuildDecryptor(keys.private_key);
auto encryptor = cryptoProvider.BuildEncryptor(keys.public_key);
std::cout << decryptor.Decrypt( encryptor.Encrypt(3) ) << std::endl;
/* /scenario 1: */
/* scenario 2: */
PublicKeyCryptoProvider cryptoProvider1;
auto keys1 = cryptoProvider1.GenerateKeys();
PublicKeyCryptoProvider cryptoProvider2;
auto encryptor2 = cryptoProvider2.BuildEncryptor(keys.public_key);
int ciphertext = encryptor2.Encrypt(3);
std::cout << decryptor.Decrypt(ciphertext) << std::endl;
// I Can't do anything bad - the API has protected me from doing bad things! Yeah!
//std::cout << cryptoProvider2.Decrypt(ciphertext) << std::endl;
/* /scenario 2: */
return 0;
}
You mentioned that you didn't think inheritance is the way to go, but there is a fairly clean way to do this with minimal inheritance.
A couple of design patterns are useful here. If you split the interface away from the implementation and think of the implementations as "always return an error" and "do something useful", you can view these two implementations as strategies and the interface as a proxy.
The proxy always forwards on it's calls to an implementation, and there is always an implementation (no need to check a flag).
The interface is initialized with a default implementation that causes an error of some kind (assert, throw, etc.). This is an example
Here's an example that I threw together that compiles with Clang 3.2:
#include <iostream>
#include <memory>
#include <cassert>
#include <stdexcept>
// Base class that defines the signatures of the functions to be forwarded.
// Another nice benefit is that each implementation can store whatever
// specific data they need.
class Impl {
public:
virtual void FuncA() = 0;
};
typedef std::unique_ptr<Impl> ImplPtr;
class ErrorImpl : public Impl {
public:
virtual void FuncA() {
assert(!"Don't call this before calling InitializeImpl!");
throw std::runtime_error("Don't call this before calling InitializeImpl!");
}
};
class OtherImpl : public Impl {
public:
void FuncA() {
std::cout << "Some other useful functionality here.\n";
}
};
// This is the class that user's will call.
class Proxy {
public:
Proxy() : impl_( ImplPtr(new ErrorImpl) ) {}
void InitializeImpl( ImplPtr ptr ) {
// You must std::move std::unique_ptr's.
impl_ = std::move( ptr );
}
void FuncA() { impl_->FuncA(); }
private:
ImplPtr impl_;
};
int main( int, char**) {
Proxy p;
// p.FuncA(); // asserts & throws.
p.InitializeImpl( ImplPtr(new OtherImpl) );
p.FuncA();
return 0;
}
If you must delay the object initialization, I would propose the usage of a proxy with an access operator throwing if the proxy is not initialized. Initialize the proxy whenever you want. You don't need an if check in each of your methods, but that check if moved to the proxy.
Some smart pointer would have been handy. But, as far as I know they don't throw if the containing pointer is uninitialized. So, you might need one of your own as given below.
#include <iostream>
class Workhorse
{
public:
void SetData (const int &data)
{
this->data = data;
}
int GetData () const
{
return this->data;
}
private:
int data;
};
template <typename T> class Proxy
{
public:
Proxy() : myObject(0)
{
}
Proxy(T* anObj) : myObject(anObj)
{
}
~Proxy()
{
delete myObject;
myObject = 0;
}
T* operator ->()const
{
if(NULL == myObject)
{
throw; // Bad object. Substitute an appropriate exception code.
}
return myObject;
}
private:
T* myObject;
};
class Worker
{
public:
Worker ()
{
}
~Worker ()
{
}
void Initialize (const int &data)
{
horse = new Workhorse;
horse->SetData(data);
}
void Action () const
{
// Here no need to check if the horse is initialized.
std::cout << horse->GetData() << std::endl;
}
private:
Proxy<Workhorse> horse;
};