Liebe Leserinnen, liebe Leser,

es gibt Fälle, wenn man den privaten Konstruktor einer Klasse mit einer der Smart-Pointer erzeugenden Funktionen der Standardbibliothek benutzen muss, aber das ist leider nicht so einfach zu tun. Ein einfaches Beispiel gibt es hier unten:

C++

1
2
3
4
5
6
7
8
9
10
// someclass.h

class SomeClass {
public:
    static std::shared_ptr<SomeClass> getInstance();
    // other funtions
    
private:
    SomeClass();
};

C++

1
2
3
4
5
6
7
8
9
// someclass.cpp

std::shared_ptr<SomeClass> SomeClass::getInstance()
{
    auto instance = std::make_shared<SomeClass>();
    // do something with instance
    
    return instance;
}

Das sieht gut aus, aber die std::make_shared Funktion kann auf den privaten Konstruktor von SomeClass nicht zugreifen, und deswegen kann die Klasse nicht erzeugt werden. Der Fehlermeldung des Compilers sagt die gleiche Sache:

make

1
2
/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/unique_ptr.h:825:30: error: ‘SomeClass::SomeClass()’ is private within this context
{ return shared_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }

Glücklicherweise ist eine Umgehung für dieses Problem mithilfe einer kleinen Vererbungszauberei möglich:

C++

1
2
3
4
5
6
7
8
9
10
// updated someclass.cpp

std::shared_ptr<SomeClass> SomeClass::getInstance()
{
    struct MkShrdEnablr : public SomeClass {};
    auto instance = std::make_shared<MkShrdEnablr>();
    // do something with instance
    
    return instance;
}

Wenn eine temporäre Klasse zu der getInstance() Funktion hinzugefügt wird, die aus SomeClass abgeleitet wurde, führt das zu dem ursprünglichen Ziel. Das ist auch bemerkenswert, dass das Vorhandensein einer temporären Klasse zu der Welt nicht freigelegt ist, weil das Rückgabewert weiterhin nur ein Pointer zu SomeClass ist, also alles wird in der urpsrünglichen Klasse zurückgewandelt, sobald die Funktion zurückkehrt.

Die Lektion des Tages ist:

Verwende eine temporäre Klasse, um eine Verbindung zwischen der Smart-Pointer erzeugenden Funktion und einer Klasse mit privatem Konstruktor zu etablieren.