To expand on my comment…
Based on your code, I guess you intend to let me specify a string name for each child widget I add to a Container
, and then later to access the child widget by name. So you'd expect me to write something like this:
class LoginController {
Container *container;
static const char *kUsernameKey = "username";
static const char *kPasswordKey = "password";
public:
LoginController() :
container(new Container())
{
container->addChild(kUsernameKey, new TextBox());
container->addChild(kPasswordKey, new TextBox());
container->addChild("button", new Button("Log In"));
container->get<Button>("button")->setAction([](){
this->login();
})
}
void login() {
string username = container->get<TextBox>(kUsernameKey)->getText();
string password = container->get<TextBox>(kPasswordKey)->getText();
sendLoginRequest(username, password);
}
};
Designing Container
this way does lookups and type checks at run time, but those lookups and type checks could be done at compile time.
Instead, design the API so that I keep my own, specifically-typed references to the children in my own variables. Looking up the children simply becomes using the variables, and no casting is necessary. The lookups and type checks are done at compile time. The code looks like this:
class LoginController {
Container *container;
TextBox *usernameBox;
TextBox *passwordBox;
public:
LoginController() :
container(new Container()),
usernameBox(new TextBox()),
passwordBox(new TextBox())
{
container->addChild(username);
container->addChild(password);
Button *button = new Button("Log In");
container->addChild(button);
button->setAction([](){
this->login();
})
}
void login() {
string username = usernameBox->getText();
string password = passwordBox->getText();
sendLoginRequest(username, password);
}
};