Biorąc pod uwagę dwie klasy A
i B
(które mogą być inteligentne typy wskaźnika), istnieją cztery główne sposoby konwertowania instancję typu B
aby wpisać A
:
A
jest dostępna baza obiekt klasy
B
(np.
B
jest publicznie wyprowadzany z
A
), a konwersja może wyciąć lub po prostu dostosować typ odniesienia lub wskaźnika.
(celowe przekreślenie).
A
ma dostępny konstruktor pobierający B
.
B
ma dostępny operator konwersji, który generuje numer A
.
Istnieje pewna funkcja, która pobiera B
i generuje A
i wywołujesz tę funkcję.
Do dziedziczenia inteligentnych wskaźników nie stosuje się do ułatwienia konwersji, ponieważ dziedziczenie pozwala na nieprawidłowe konwersje; stąd uderzenie wyżej. Na przykład, jeśli SmartPtr<Derived>
odziedziczony publicznie z SmartPtr<Base>
, wtedy można byłoby zrobić SmartPtr<Base>& spBase = spDerived;
, a następnie np. spBase = spOtherDerived
, który byłby raczej problematyczny ... Na odpowiednio wysokim poziomie abstrakcji jest to zasadniczo ten sam problem, co dla const
dla konwersji wskaźnika; zobacz element FAQ: 18.17 "Why am I getting an error converting a Foo** → Foo const**?".
Tak więc, inteligentne konwersje wskaźnika są generalnie wyrażane za pomocą ostatnich trzech punktów, a mianowicie konstruktorów, operatorów konwersji i nazwanych funkcji konwersji.
Zasadniczo istnieją trzy inteligentne wskaźniki w C++ 0x, nie zważając na nieaktualnych auto_ptr
:
std::unique_ptr
dla pojedynczych obiektów.
std::unique_ptr
dla tablic.
std::shared_ptr
dla pojedynczych obiektów.
unique_ptr
wyraża przeniesienie własności, jak stary auto_ptr
zrobił i robi. Ale auto_ptr
nie obsługuje tablic. unique_ptr
ma, i to wpływa na możliwe konwersje.
W przypadku pojedynczych obiektów, unique_ptr
obsługuje konwersje, które wykonuje odpowiednie wskaźniki surowe, za pośrednictwem konstruktorów. Ma szablonowego konstruktora pobierającego unique_ptr
innego typu. Zobacz np. Projekt C++ 0x N3126 §20.9.10.2.
Ale dla tablic, które byłyby tak samo niebezpieczne, jak w przypadku surowych wskaźników! I tak dla tablic unique_ptr
ma nie oferują podstawową/pochodną konwersji. Zobacz np. Projekt C++ 0x N3126 §20.9.10.3.
Od unique_ptr
wyraża przeniesienie własności podczas shared_ptr
wyrażona współwłasność nie może być bezpieczny ogólny konwersja z shared_ptr
do unique_ptr
. Jednak w inny sposób, Boost shared_ptr
ma konstruktora biorąc auto_ptr
, a C++ 0x shared_ptr
zachowuje to (również ma) i oczywiście dodaje konstruktora biorąc unique_ptr
. Patrz szkic C++ 0x N3126 §20.9.11.2/1.
shared_ptr
dostarcza konwersji bazowych/pochodnych za pośrednictwem konstruktorów i za pomocą darmowych funkcji, które koncepcyjnie realizują "rzutowania". Zasadniczo oznacza to, że shared_ptr
jest dość niebezpieczny do użycia bezpośrednio dla tablic obiektów typu klasy. W tym celu zapakuj go.
Konwersja z shared_ptr
na unique_ptr
jest, jak wspomniano, nie jest obsługiwana jako operacja ogólna. Ponieważ własność dzielona nie jest bezpośrednio zgodna z przeniesieniem własności. Pomijając jednak komplikacje. wątku bezpieczeństwa, shared_ptr::unique
mówi, czy istnieje jeden właściciel (a mianowicie Twoje wystąpienie), a następnie, jeśli masz wymaganą wiedzę o tym, jak zbudowany został pierwotny shared_ptr
, możesz użyć funkcji bezpłatnej get_deleter
, aby uzyskać wskaźnik do funkcja deletera, i wykonaj niektóre szantanowania niskiego poziomu. Jeśli rozumiesz całkowicie, o czym tu mówię, to dobrze, dobrze. Jeśli nie, to najlepiej, że nie podaję więcej szczegółów, ponieważ jest to bardzo szczególny przypadek i wymaga najwyższej staranności oraz, że naprawdę wiesz, co robisz, ™. ;-)
Cóż, o to chodzi. Nie dyskutuję o weak_ptr
, ponieważ jest to tylko część funkcji shared_ptr
. Ale mam nadzieję, że powyższe jest o to pytasz.
@sonicoder: 'unikalne_ptr' jest niekodowane, tak jak' scoped_ptr' jest nieoprawione. Semantyka 'unique_ptr' i' scoped_ptr' nie jest oczywiście identyczna, ponieważ 'unique_ptr' może zostać przeniesiony, ale są one podobne i jest bardzo mało przypadków, w których używałbyś' scoped_ptr', ale 'unique_ptr' byłoby niepożądane. –