Ich lese Artikel 28 auf Smart Pointer von Scott Meyers Effektiver C++ und haben die folgende Frage.Mehrdeutigkeit im Funktionsaufruf implizit umwandeln Smart-Zeiger
Eine vollständige Demonstration kann bei http://ideone.com/aKq6C0 gefunden werden.
class Base {};
class Derived : public Base {};
void foo(Base* b) { cout << "foo called on Base pointer" << endl;}
Derived *d = new Derived();
foo(d); //No problem
Aber solche implizite Umwandlung kann nicht für Smartpointer, d.h. SmartPtr<Derived>
implizit konvertiert werden können, nicht auf SmartPtr<Base>
geschehen:
Eine abgeleitete Klasse kann Zeiger implizit auf einen Basisklassenzeiger umgewandelt werden. So verwenden wir ein Mitglied Vorlage für solche Umwandlungen:
template<typename T>
class SmartPtr {
public:
//constructors, operator->, etc
//member template for type conversion
template<NewType>
operator SmartPtr<NewType>() {
return SmartPtr<NewType>(pointee);
}
private:
T* pointee;//the raw pointer
};
Dies kann fast arbeiten, aber es kann dazu führen, Zweideutigkeit:
class Remote {};
class Base : public Remote {};
class Derived : public Base {};
void foo(const SmartPtr<Remote>& p) { cout << "remote" << endl;}
void foo(const SmartPtr<Base>& p) { cout << "base" << endl;}
SmartPtr<Derived> d(new Derived());
foo(d);//compile error: ambiguity
In diesem Beispiel wird der Compiler nicht weiß, ob es d
umwandeln sollte SmartPtr<Base>
oder SmartPtr<Remote>
, obwohl für einen rohen Zeiger Base
offenbar überlegen ist. Das Buch sagt
Das Beste, was wir tun können, ist, Member-Vorlagen zu verwenden, um Konvertierungsfunktionen zu generieren, und dann Casts in den Fällen zu verwenden, in denen Mehrdeutigkeiten auftreten.
Aber wie genau wenden wir hier an? foo(static_cast<SmartPtr<Base>>(d))
kompiliert auch nicht. Aus der Fehlermeldung kann ich sagen, dass der Fehler von der Verwendung von nicht-const Referenz im Copy-Konstruktor SmartPtr
kommt. Ich frage mich, was ist der richtige Weg, um den Funktionsaufruf zu machen.
Nicht qustion beantworten zu binden, wäre in der Lage, aber 'Rückkehr SmartPtr (pointe e); 'scheint nicht richtig, Sie brauchen etwas wie' std :: week_ptr ', um dies zu tun –
Sie sollten sich die Standard-Smart-Pointer ansehen, und wie sie Umwandlung von 'std :: shared_ptr' zu 'std bereitstellen :: shared_ptr 'wenn (und nur wenn)' Derived * 'ist konvertierbar zu' Base * '. –
Ihre Besetzung ist korrekt, was fehlt, ist Code für Ihre Kopierkonstruktoren. Wenn Sie einen haben, der non-const ref nimmt - würden Sie den Fehler erhalten, den Sie erwähnten, wenn Sie ref einfach zu const in Kopie ctor ändern können und Code würde kompilieren (geprüft) –