2010-05-10 3 views
13

Jaki jest cel następujących ezoterycznych operatorów C++?Ezoteryczni operatorzy C++

wskaźnik z członem

::* 

Bind wskaźnika z członem przez wskaźnik

->* 

Bind wskaźnik do członka poprzez odniesienie

.* 

(reference)

+9

Niezależnie od wikipedia, ':: *' nie jest operatorem. –

Odpowiedz

24

Wskaźnik do elementu pozwala mieć wskaźnik, który jest względem konkretnej klasy.

Załóżmy, że masz klasę kontaktów z wieloma numerami telefonów.

class contact 
{ 
    phonenumber office; 
    phonenumber home; 
    phonenumber cell; 
}; 

Chodzi o to, czy masz algorytmu, który musi użyć numeru telefonu, ale decyzję, której numer telefonu powinny być wykonane poza algorytmem, wskaźniki do członka rozwiązania problemu:

void robocall(phonenumber contact::*number, ...); 

teraz wywołujący robocall może zdecydować, jaki rodzaj PHONENUMBER używać:

robocall(&contact::home, ...); // call home numbers 
robocall(&contact::office, ...); // call office number 

.* i ->* wchodzić w grę raz masz wskaźnik. Więc wewnątrz robocall, zrobiłbyś:

contact c = ...; 
c.*number; // gets the appropriate phone number of the object 

czyli

contact *pc = ...; 
pc->*number; 
+0

To naprawdę fajne. –

+0

W InformIT znajduje się czytelny przewodnik [Wskaźniki dla członków] (http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=142). –

+0

Oto ich ładny przykład: http://msdn.microsoft.com/en-us/library/k8336763.aspx –

2

Zapoznaj się z C++ FAQ Lite's section on pointers to member functions. Wyszukaj określonych "operatorów", o których mówisz (w większości przeglądarek Ctrl-F otwiera okno dialogowe Znajdź/Wyszukaj, które umożliwia wyszukiwanie tekstu na stronie internetowej) i powinno pomóc ci lepiej zrozumieć rzeczy.

0

Przesadnie uproszczona odpowiedź - operatory te umożliwiają wywoływanie funkcji członków jako "zwykłych" funkcji (przynajmniej wygląda to tak samo z perspektywy użytkownika końcowego). Przykład z rzeczywistego świata - są one często używane w różnych implementacjach wywołań zwrotnych.

4

Nie ma takiego operatora, jak ::* i nigdy nie było. Nie wiem, skąd to masz.

chodzi o ->* i .* - są operatorzy Dereferencjuj wskaźników z wskaźnik do członka typu.

struct S { 
    int i; 
}; 

int main() { 
    int S::*pi = &S::i; // pointer of pointer-to-member type 

    S s; 
    S* ps = &s; 

    s.*pi = 0; // operator `.*` used 
    assert(s.i == 0); 

    ps->*pi = 1; // operator `->*` used 
    assert(s.i == 1); 
} 

Co do tego, co podpowiadają członkowie, to ... co powie twoja ulubiona książka w C++ na ten temat?

+0

Mam :: * z wikipedii wymienionych jako odniesienie do mojego pytania. –

+0

:: * kompiluje się dobrze w g ++. –

+0

@Neil G: Co dokładnie "kompiluje się dobrze w g ++"? – AnT

0

Umożliwia to wyświetlanie wskaźników do funkcji składowych (i zmiennych składowych), które są powiązane z konkretnym wystąpieniem klasy.

Wskaźniki do funkcji elementów mogą być przydatne do takich rzeczy jak lekkie implementacje wzorca stanu.Generalnie, za każdym razem, gdy chcesz zmienić zachowanie obiektu w czasie bez uciekania się do wyłączania całego obiektu, możesz rozważyć użycie wskaźników do funkcji członków.

Wskaźniki do zmiennych składowych mogą być użyte, jeśli chcesz np. Zaimplementować ogólny algorytm przeszukiwania tablicy struktur dla pozycji, która ma określoną wartość dla danego pola.

3

Dotyczą one funkcji wskaźników do członków i wskaźników do członków.

struct Foo { 
    int a() { return 1; } 
    int b() { return 2; } 
    int c; 
}; 

int main() { 
    Foo f; 
    f.c = 3; 

    typedef int (Foo::*member_fn)(); // pointer-to-member-function 
    typedef int (Foo::*data_member); // pointer-to-member 

    member_fn mf = &Foo::a; 
    (f.*mf)(); // calls the member function pointed to by mf. returns 1 
    mf = &Foo::b; 
    (f.*mf)(); // This time, returns 2, since mf points to b 
    Foo *fp = &f; 
    (fp->*mf)(); // same thing, via pointer to f instead of object/reference f. 

    data_member dm = &Foo::c; 
    f.*dm; // is 3 
    f.*dm = 5; 
    f.c; // is now 5. 

    Foo f2; // another instance 
    f2.c = 12; 
    f2.*dm; // is 12. Same pointer-to-member, different object. 
} 

Chociaż może wyglądać jak jeden, ::* nie jest operatorem. Jest to operator :: i modyfikator typu * obok siebie. Aby to udowodnić bez odwoływania się do standardu, spróbuj dodać spacje: :: * kompilacje, . * nie, ani nie ma -> *.

Co do tego, do czego są one faktycznie przydatne - ta sama zasada co wskaźniki funkcji. Nie używałbyś ich tak jak powyżej, w sytuacji, w której możesz po prostu wywołać funkcję po nazwie, ale możesz przekazać je jako parametry lub zwrócić je z funkcji, zapisać lub wybrać jedną z kilku na podstawie skomplikowanej logiki.

Jeśli to pomoże, wierzę składnia jest tak dobrana, że ​​chociaż .* jest niepodzielny pojedynczy operator, można sobie wyobrazić, że *dm „oznacza” c, element wskazywany przez DM. Więc jeśli dm wskazuje na c, to f.*dm jest taki sam jak f.c.