MFC C++ Class member variable, use instead the constructor with parameter - c++

This is MFC C++ (not C++ 0x11). I have a class, with a member variable of a CDerivedComboBox, call it, CMyForm. I want to make a constructor for CDerivedComboBox, that passes in a parameter, so when I declare it, I can either pass a flag or not.
For example in .h file, two constructors
CDerivedComboBox();
CDerivedComboBox(bool specialFlag);
It compiles fine when adding that constructor implementation, but in my class using it, I can't figure out how to actually create one calling that constructor. Is this not possible in C++/
CDerivedComboBox combo; // works
CDerivedComboBox comboParam(true); // does not work

The CDerivedComboBox should be a member of your CMyForm. It appears you want to dynamically call a different ctor for CDerivedComboBox at runtime. Therefore, I would recommend making the member be a pointer to a CDerivedComboBox:
class CMyForm
{
CDerivedComboBox *m_pMyCombo;
}
CMyForm::CMyForm(..., CWnd *pParent = NULL) : m_pMyCombo(NULL)
{
if (somecondition)
m_pMyCombo = new CDerivedComboBox();
else // use specialFlag
m_pMyCombo = new CDerivedComboBox(specialFlag);
}
Remember to delete m_pMyCombo in dtor!

Related

Correct way to implement singleton with shared pointer?

I'm attempting my first bigger C++ object and I'm running into a bit of a problem when it comes to implementing a singleton using a shared pointer.
When I try to compile the following, I Visual Studio gives me this error:
"Error C2248 'PaletteManager::PaletteManager': cannot access private
member declared in class 'PaletteManager' {omitted}\xmemory line 228"
I'm guessing the issue is because I have a private constructor/destructor and make_shared is trying to call the constructor. This access problem makes sense to me, but if I want to use a shared pointer as the way to access my singleton object, what am I supposed to do? The code works just fine with a raw pointer, but I wanted to try and do things the clean way with a smart pointer.
Here is the header file for the code in question:
class PaletteManager
{
private:
// array representing palette colors
uint* paletteColors;
// private constructor/destructor because singleton
PaletteManager();
~PaletteManager();
// load palette from file TODO: not implemented
void loadPallette();
static std::shared_ptr<PaletteManager> instance;
public:
const uint PALETTE_MAX_COLORS = 4;
uint getPaletteColor(uint idx);
// singleton accessor
static std::shared_ptr<PaletteManager> getInstance();
};
And here is the function at issue in the cpp file:
std::shared_ptr<PaletteManager> PaletteManager::instance = nullptr;
std::shared_ptr<PaletteManager> PaletteManager::getInstance()
{
if (!PaletteManager::instance)
{
PaletteManager::instance = std::make_shared<PaletteManager>();
}
return PaletteManager::instance;
}
PaletteManager::instance = std::make_shared<PaletteManager>();
This results in std::make_shared attempting to new a PalletteManager object, and then construct a std::shared_ptr from it. This is what std::make_shared does, that's how it works.
This is not going to work here: that's because PalletteManager has a private constructor, and std::make_shared, the template in the C++ library, is not it's friend.
You will have to explicitly new the object in getInstance, a member of this class, which can use the private constructor, and then manually construct the std::shared_ptr from the pointer to this new object.
TLDR: you cannot use std::make_shared for an object with a private constructor. C++'s rules do not allow you to do that.
You can make std::make_unique<>() a friend function of your class with the private constructor. Presumably this would work with std::make_shared<>() too? (But I haven't tested it.)
For example, see:
How to make std::make_unique a friend of my class

How to pass a delegate^ to a native class in c++/cli

I have a native class
public NativeClass:
{
public:
typedef void(*Func)(cv::UMat image);
void setFunc(Func func);
}
and would like to pass a function as parameter from managed class.
ref ManagedClass:
{
public:
ManagedClass()
{
NativeClass* nativeClass = new NativeClass();
nativeClass.setFunc(doSomething);
}
private:
doSomething(cv::UMat image)
{
//do something
}
}
But it seems to not work. How can I get this to work?
Before you pass the delegate as a function pointer, you need to create a delegate first.
In C#, you just need to reference the method name without parenthesis. In C++/CLI, you need to explicitly call the delegate constructor, and you need to pass explicit parameters of the object to call the method on, and the method in a C++-style.
MyDelegate^ del = gcnew MyDelegate(this, &ManagedClass::doSomething);
// Explicit ctor ^^^^^^^^^^^^^^^^
// Pass the object to be called on ^^^^
// Pass the method in the C++ style ^^^^^^^^^^^^^^^^^^^^^^^^^^
Once you have that, you can just pass the delegate to the method that takes a raw function pointer. It knows how to convert the managed delegate object to a function pointer. There's a good example in Microsoft's documentation. You must be sure to keep around the managed delegate object forever. As soon as the managed delegate is garbage collected, the raw function pointer stops working.
Once you have that, you'll need to look at your parameter type, cv::UMat. I don't know what type that is or where you're getting it, but you may need to adjust your parameter type on the managed side, the unmanaged side, or both. (This is why I didn't declare the delegate type in my example above; I wasn't sure what would work so I left it generic. If everything works, then you might be able to use Action<cv::UMat> as your delegate type.)

How would I use a library that extends libev in a C++ object?

I am trying to implement a wrapper for a library called libumqtt. Libumqtt is a C library that uses libev to have callbacks for events from the MQTT protocol.
What I didn't realize until the other day is that I cannot pass a member function to a function that expects a normal, static function. This causes problems as I was planning on launching multiple instances of libumqtt to handle multiple connections at the same time.
My code is in C++ as that is the most convenient to use with the Godot's (a game engine) GDNative module.
While researching for either a way to sandbox multiple instances of a c library or to somehow get the pointers to work anyway, I found this answer. I do not understand this quote from the answer:
If you need to access any non-static member of your class and you need
to stick with function pointers, e.g., because the function is part of
a C interface, your best option is to always pass a void* to your
function taking function pointers and call your member through a
forwarding function which obtains an object from the void* and then
calls the member function.
What I am trying to do is setup callbacks that libev will use to send the data to the right instance of my object when it is handling potentially up to 500 or more connections simultaneously.
Will passing void* help me with my goals and how would I implement this? Also, how does a forwarding function work?
Edit: To Provide Code Example That Walnut Is Asking For
This example below comes from a version of my class that uses static functions. If I tried to use run this when the functions are not static, then I would get an error about not being able to pass in a member function in place of a regular function.
// Client.cpp
void Client::signal_cb(struct ev_loop *loop, ev_signal *w, int revents) {
ev_break(loop, EVBREAK_ALL);
}
// ...
void Client::do_connect(struct ev_loop *loop, struct ev_timer *w, int revents) {
//Godot::print("Attempt MQTT Start!!!\n");
//write_log("debug", "MQTT Wrapper - Attempt MQTT Start!!!");
struct umqtt_client *cl; // Move to Class Access (Private)?
cl = umqtt_new(loop, cfg.host, cfg.port, cfg.ssl);
if (!cl) {
//Godot::print("Failed To Create Client!!!\n");
//write_log("debug", "MQTT Wrapper - Failed To Create Client!!!");
start_reconnect(loop);
return;
}
//Godot::print("Setup Client Callbacks!!!\n");
//write_log("debug", "MQTT Wrapper - Setup Client Callbacks!!!");
// For StackOverflow: These cl->... lines do not work because of not being able to pass a member function as a regular function. These are the main callbacks I have trouble with.
// How do I convert from `void (libumqtt::Client::*)(struct umqtt_client *)` to `void (*)(struct umqtt_client *)`?
cl->on_net_connected = Client::on_net_connected; // Pass member function as a non-static object
cl->on_conack = Client::on_conack; // Pass member function as a non-static object
cl->on_suback = Client::on_suback; // Pass member function as a non-static object
cl->on_unsuback = Client::on_unsuback; // Pass member function as a non-static object
cl->on_publish = Client::on_publish; // Pass member function as a non-static object
cl->on_pingresp = Client::on_pingresp; // Pass member function as a non-static object
cl->on_error = Client::on_error; // Pass member function as a non-static object
cl->on_close = Client::on_close; // Pass member function as a non-static object
//Godot::print("MQTT Start!!!\n");
//write_log("debug", "MQTT Wrapper - MQTT Start!!!");
}
void Client::initialize() {
// For StackOverflow: These two lines cannot work in an object as libev expects signal_cb and do_connect to be regular functions. These callbacks are also necessary, but I am not sure how to handle this.
ev_signal_init(&signal_watcher, Client::signal_cb, SIGINT);
ev_timer_init(&reconnect_timer, Client::do_connect, 0.1, 0.0); // Fix Me - Make ev.h object
// ...
}
Edit: I should mention I am a noob at using C and C++. The most I've done in it before is testing a buffer overflow. So, if their's anything I am obviously doing wrong, I would appreciate the tip in the comments.
So the issue is that umqtt_client does not seem to provide any way of passing additional user data to the callback (the void* mentioned in your quote). It expects the callback to take just a pointer to the umqtt_client instance. (I may be wrong here, I am basing this just on a quick look at the source files.)
If your member functions don't actually access any non-static member of your class, then you can simply make them static. Then you can use them directly as normal function pointers.
Otherwise you need to obtain a pointer to your instance from the umqtt_client* pointer.
One way of doing this would be to maintain a static map between the pointers, e.g. in Client add a declaration:
static std::map<umqtt_client*, Client*> umqtt_client_map;
and insert into it when creating a Client (I will assume here that you actually maintain the cl pointer as class member of Client), preferably in Client's constructor:
umqtt_client_map[cl] = this;
Then in Client's destructor (or where ever the umqtt_client object is destroyed) erase the corresponding element from the map:
umqtt_client_map.erase(cl);
Then you can use a lambda looking like this to pass as callback:
cl->on_net_connected = [](umqtt_client* ptr){
umqtt_client_map[ptr]->on_net_connected();
};
Note that on_net_connected won't need the pointer as argument if it is a member of the class.
This also assumes that you make the class non-copyable and non-movable or that you implement the copy- and move-constructor and -assignment operators with the correct semantics of erasing and inserting into umqtt_client_map as well.
The library seems to offer a function umqtt_init instead of umqtt_new that doesn't allocate the umqtt_client object. If you use that instead you could do the following:
Wrap the umqtt_client in a small standard-layout class:
struct umqtt_client_wrapper {
umqtt_client cl; // must be first member!
Client* client;
static_assert(std::is_standard_layout_v<umqtt_client_wrapper>);
};
You would then use that as member of Client instead of umqtt_client* directly and initialize the umqtt_client* with umqtt_init) andclientwiththisinClient`'s constructor. Then you can use a cast in the lambda for the callback:
cl->on_net_connected = [](umqtt_client* ptr) {
reinterpret_cast<umqtt_client_wrapper*>(ptr)->client->on_net_connected();
};
Note that this depends on umqtt_client_wrapper being standard-layout and that umqtt_client* is its first member. Not following these rules will cause undefined behavior. The static_assert gives some assurance that at least part of it is not accidentally violated. It requires #include<type_traits> and C++17 in the form that I used here.
Again this requires special care to implement the copy- and move- special member functions of Client correctly or to delete them, but with this method no action in the destructor is required.
This approach is more performant than the other one and in principle you could avoid the extra Client pointer if you make sure that Client itself is standard-layout, but that is probably too restrictive and risky.
Another way, saving the extra indirection, is to use the wrapper as a base class of Client:
struct umqtt_client_wrapper {
umqtt_client cl; // must be first member!
static_assert(std::is_standard_layout_v<umqtt_client_wrapper>);
};
Then let Client inherit from umqtt_client_wrapper and you can use:
cl->on_net_connected = [](umqtt_client* ptr) {
static_cast<Client*>(reinterpret_cast<umqtt_client_wrapper*>(ptr))
->on_net_connected();
};
Note that here the first cast must be static_cast, otherwise you could easily cause undefined behavior.
The same remarks as before apply.

Reassign object with different constructor

In class MyClass, I have a member Dialog dialog_.
After MyClass's constructor is called, I want to call a different constructor for dialog_ with parameters that are created in MyClass's constructor (that's why I can't directly call the different constructor for dialog_, but just the default one).
So I tried
dialog_ = Dialog(/* different constr. w/ parameters passed from MyClass */);
But that doesn't work. The error is
Error: no operator "=" matches these operands
operand types are: Dialog = Dialog
So I Googled a bit and found in this SO thread (3rd answer) a code snippet which I tried:
dialog_.~Dialog();
new(&dialog_) Dialog(/* different constr. w/ parameters passed from MyClass */);
And it works. The answer in the thread though states "The value of this does not go beyond purely theoretical though. Don't do it in practice. The whole thing is ugly beyond description."
So what can I do to solve my problem without using that obviously frowned upon piece of code?
I hope you understand what I'm trying to achieve. Thanks!
There are two ways to achieve what you want.
In c++98 you need to defer some of your initialisation to an init() function that you call from the constructor. This is a bit icky because it means a redundant construction and assignment for a number of your member variables.
In c++11 you can call 1 other constructor in the initialiser list, passing computed values (these values can be computed in static functions for cleanliness).
If you provide an example of your constructor code I can show you how to do it.
You can put the Dialog member in a std::unique_ptr and then replace it when you need:
class MyClass {
private:
std::unique_ptr<Dialog> dialog_;
public:
MyClass():
dialog_( /* ... first constructor ... */ ) {}
void setNewDialog(/* parameters */) {
dialog_.reset(new Dialog(/* parameters */) );
}
};
Nothing I've tried is working, so I'll just use
dialog_.~Dialog();
new(&dialog_) Dialog(/* ... */);
even though it's bad

How sensible is it to pass functions to initialisation lists in a constructor?

Let's say I have a class Engine that looks a bit like this:
class Engine
{
public:
private:
Game * m_pGame;
}
And then I want to use an initialisation list for it's constructor:
// Forward declaration of the function that will return the
// game instance for this particular game.
extern Game * getGame();
// Engine constructor
Engine::Engine():
m_pGame(getGame())
{
}
Is that initialiser for m_pGame sensible?
What I mean is - is it OK/good practice to use a function to initialise a member variable in a constructor?
Initialiser lists don't care how the values get there. What you have to worry about is making sure that a reasonable value is provided. If getGame() is sure to return a valid pointer, then there's no reason why this would be a problem.
Perhaps a better question is, why don't you call getGame first and pass that in as an argument? eg:
Engine::Engine(Game* game):
m_pGame(game)
{
}
// later...
Engine* the_engine = new Engine(getGame());
That gives you more flexibility over how you configure an Engine in future, and doesn't hard-code the dependency on the getGame function.