Strukturieren Sie die Klasse Control so um, dass sie keinerlei private Instanzvariablen oder -methoden besitzt,
natürlich mit Ausnahme eines Pimpl-Zeigers. Das Ziel soll es sein, dass die interne Realisierung der Klasse Control
noch Änderungen unterworfen sein kann, man aber alle anderen C++-Dateien, die die Control-Klasse verwenden wollen,
von (überflüssigen) Neuübersetzungen ausnehmen möchte.
Nehmen Sie die Umstrukturierung in folgenden Schritten vor:
-
Fügen Sie alle privaten Mitglieder, sowohl Daten als auch Methoden, in eine separate Hilfsklasse ein. Benennen Sie diese Klasse
ControlPimpl. -
Ergänzen Sie in der Header-Datei der Ausgangsklasse eine Forward-Deklaration für die
ControlPimplwie folgt:
// file Control.h:
class ControlPimpl;- Deklarieren Sie in der Ausgangsklasse einen Zeiger auf die
ControlPimpl-Klasse auf Basis einerstd::unique_ptr-Variablen. Dies sollte die einzige private Instanzvariablen der Ausgangsklasse sein:
class Control {
private:
// single property: opaque pointer / pointer to impl
std::unique_ptr<ControlPimpl> m_pimpl;
public:
// public class interface
Control();
void setText(std::string);
void resize(const int width, const int height);
void show();
void hide();
};- Fügen Sie die
ControlPimpl-Klassendefinition in der Quelldatei der Ausgangsklasse ein. Übernehmen Sie alle Instanzvariablen (Eigenschaften und Methoden, sowohlpublicals auchprivate) direkt in dieControlPimpl-Klassendefinition:
class ControlPimpl {
private:
std::string m_text;
int m_width;
int m_height;
bool m_visible;
void draw();
public:
ControlPimpl() : m_text(""), m_width(0), m_height(0), m_visible(true) {}
void setText(const std::string& text);
void resize(const int width, const int height);
void show();
void hide();
};- Die öffentliche Schnittstelle (
public) der Ausgangsklasse spiegeln Sie mit entprechenden Aufrufen an der Pimpl-Klasse wider, um so gewissermaßen die öffentliche Schnittstelle (public) der Ausgangsklasse an die Pimpl-Klasse durchzuschleusen.
void Control::setText(const std::string& text)
{
m_pimpl->setText(text);
}
...
...- Die private Schnittstelle (
private) der Ausgangsklasse implementieren Sie wie gewünscht bzw. erforderlich. Nachträgliche Änderungen haben keine Auswirkungen auf Benutzer der Ausgangsklasse:
void ControlPimpl::draw()
{
std::cout
<< "control "
<< std::endl
<< " visible: "
<< std::boolalpha
<< m_visible
<< std::noboolalpha
<< std::endl
<< " size: "
<< m_width
<< ", "
<< m_height
<< std::endl
<< " text: "
<< m_text
<< std::endl;
}- Die Pimpl-Klasse wird im Konstruktor der Ausgangsklasse instanziiert:
Control::Control() : m_pimpl(std::make_unique<ControlPimpl>()) {}Siehe Control.h und Control.cpp sowie Client.cpp.
Siehe Control.h und Control.cpp sowie Client.cpp.
Siehe Control.h, ControlPimpl.h, Control.cpp und ControlPimpl.cpp sowie Client.cpp.