I'm trying to create a C++ class hierarchy of UI "view" classes that wrap platform-specific UI classes. My classes use the pimpl idiom to hide the implementation from the header file. The Impl
structs contain another pointer, to classes in the platform hierarchy.

(I used "PS" to abbreviate "platform specific".)
In the code below, I try to show a boiled down example of the base class (View
), and one derived class (Button
), along with the classes that they wrap. There is a static cast in the Button's
implementation. All of the subclasses of View
will have a lot of these casts. Is there way define the Impl
struct so that the compiler understands the types better here, so I don't need to use the static casts?
// In .hh file
class View {
public:
virtual ~View() = default;
...
protected:
struct Impl;
Impl *impl;
View();
View(Impl *impl);
};
class Button: public View {
public:
Button();
void setText(const string &text);
};
// In .cc file
View::View() :impl(nullptr) {}
View::View(Impl *impl) :impl(impl) {}
struct View::Impl {
PSView *psView;
};
void View::doStuff() {
... impl->psView ... // fine, no cast needed here
}
Button::Button() {
PSButton *b = new PSButton();
impl = new Impl{b};
}
void Button::setText(const string &text) {
PSButton *myImpl = static_cast<PSButton*>(impl->psView);
myImpl->setTitle(text);
}
In my real code, it's a bit weirder, because the platform specific types are Apple's Objective-C classes. I'm putting that aside for now to try and clean up and simplify this question.