c++ private member zugriff - Trick erklärung gesucht

OP #4489496
Lesenswert?

Hi,
ich würde mich jetzt nicht gerade unerfahren in C++ nennen, aber
das kapier ich überhaupt nicht:

http://bloglitb.blogspot.de/2011/12/access-to-private-members-safer.html

Kann mir jemand erklären, was da passiert? Bzw, warum das funktioniert 
(weil das tut es ohne compiler warnung)?

Weder der Code noch die Erklärung bringt mich weiter.
Was ist ein "Tag"? ich kenn den Begriff nur von den C-Strukturnamen.

wie funktioniert das mit dem Templateparameter M, der ja zurückgegeben 
wird. Sieht hier aus, wie eine Textersetzung, aber c++ templates sind 
dies ja explizit nicht.
Wie funktioniert das friend im Rob? wozu die inline Friend deklarationen 
mit definition?
oder firend definition im A_f.

Oder warum funktioniert der Aufruf a.*get ?

Ich fühl mich gerade, als hätte ich noch nie C++ geschrieben O_o
#4489566
Lesenswert?

Der eigentliche Trick an dem Ganzen scheint wohl zu sein, dass bei einer 
expliziten Instanzierung die üblichen Zugriffsregeln nicht gelten (siehe 
letzter Kommentar auf der Seite). Also gibt es bei der Zeile
1
template struct Rob<A_f, &A::a>;
keinen Fehler, obwohl A::a private ist. Der restliche Code dreht sich 
wohl darum, dass die get Funktion per ADL (Argument Dependent Lookup) 
gefunden wird und die gewünschte Adresse auf die private Variable zurück 
liefert.

Um die richtige Funktion zu finden wird hier quasi Tag Dispatch genutzt. 
Wenn man das Beispiel mit mehreren Klassen und Variablen machen möchte 
muss man die get Funktionen irgendwie unterscheiden. Das passiert durch 
durch den einzigen Parameter dieser Funktion.

Edit: So sähe es ohne Tags aus:
1
#include <iostream>
2

3
template <class T, T ptr>
4
struct Rob
5
{
6
  friend T get() {
7
    return ptr;
8
  }
9
};
10

11
// use
12
struct A {
13
  A(int a):a(a) { }
14
private:
15
  int a;
16
};
17

18
template struct Rob<int A::*, &A::a>;
19
int A::* get();
20

21
int main() {
22
  A a(42);
23
  std::cout << "proof: " << a.*get() << std::endl;
24
}
OP #4489633
Lesenswert?

ccc schrieb:
> Was macht denn das
> int A::*

"int A::* "  heißt, es handelt sich um einen Member-Pointer auf ein int.

"get()" liefert genau einen solchen Pointer zurück. dieser muss 
dereferenziert werden mittels "a.*get()"  da es ein Memberpointer ist, 
kann dieser nur mit einer Instanz dereferenziert werden, das passiert 
durch das a.*<memberpointer>.
#4489655
Lesenswert?

Vlad T. schrieb:
> warum ist die Zeile "int A::* get();" nötig?
> ich dachte, das wird durch die Rob-friend definition erledigt -->
> http://en.cppreference.com/w/cpp/language/friend (2)

Irgendwelche wirren Regeln. Es gibt zwar eine Definition für die 
Funktion aber irgendwie keine globale Deklaration. Durch ADL kann man 
die Funktion auch finden aber wohl nicht einfach so wenn man keine extra 
Deklaration hinzufügt.
OP #4489658
Lesenswert?

Sebastian V. schrieb:
> Irgendwelche wirren Regeln. Es gibt zwar eine Definition für die
> Funktion aber irgendwie keine globale Deklaration. Durch ADL kann man
> die Funktion auch finden aber wohl nicht einfach so wenn man keine extra
> Deklaration hinzufügt.

Kurios und eigentlich ein Wunder, das die Compilerhersteller da durch 
sehen und vor allem Compiler erzeugen die unterienander weitestgehend 
das selbe machen ^^.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren