Forum: PC-Programmierung c++ private member zugriff - Trick erklärung gesucht


von Vlad T. (vlad_tepesch)


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

von Sebastian V. (sebi_s)


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
}

: Bearbeitet durch User
von Vlad T. (vlad_tepesch)


Lesenswert?

ah, ok. die ganzen Member-Pointer Konstrukte haben mich verwirrt.
Die braucht man ja sonst kaum.

edit:
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)

: Bearbeitet durch User
von ccc (Gast)


Lesenswert?

template struct Rob<int A::*, &A::a>;

Was macht denn das
int A::*
?

Und wieso steht da a.*get() und nicht *a.get()?

von Vlad T. (vlad_tepesch)


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>.

: Bearbeitet durch User
von Sebastian V. (sebi_s)


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.

von Vlad T. (vlad_tepesch)


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 ^^.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.