2016-08-22 1 views
1

Ich bin kürzlich in diese ganze Welt von Klassen, Vererbung und Templates in C++ gesprungen. Aber ich bin stecken geblieben. Bitte schlagen Sie mir einen Weg vor, dieses Problem zu lösen.Wie auf die Adresse des Basisklassenmembers in geerbten Klassenmemberfunktionen zugreifen?

#include <iostream> 

using namespace std; 

template <typename type> 
class a 
{ 
protected: 
    type *b; 
}; 

template <typename type> 
class p : public a<type> 
{ 
public: 
    void f() 
    { 
    type **q = &a<type>::b; 
    cout << *q << endl; // some other code in reality related to (*q) 
    } 
}; 

int main() 
{ 
    p<int> obj; 
    obj.f(); 
    return 0; 
} 

Aber es stellte sich als nicht erfolgreich erwiesen:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’: 
x.cpp:26:9: required from here 
x.cpp:9:9: error: ‘int* a<int>::b’ is protected 
    type *b; 
     ^
x.cpp:18:16: error: within this context 
    type **q = &a<type>::b; 
       ^
x.cpp:18:26: error: cannot convert ‘int* a<int>::*’ to ‘int**’ in initialization 
    type **q = &a<type>::b; 
         ^

So konvertiert ich type* a<type>::* q = &a<type>::b;type **q = &a<type>::b;. Dann bekam ich einen zusätzlichen Fehler:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’: 
x.cpp:26:9: required from here 
x.cpp:9:9: error: ‘int* a<int>::b’ is protected 
    type *b; 
     ^
x.cpp:18:26: error: within this context 
    type* a<type>::* q = &a<type>::b; 
         ^
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member 
    cout << *q; 
      ^

So konvertierte ich b zu einem public: Mitglied class a von protected:. Aber das gibt mir auch einen Fehler:

x.cpp: In instantiation of ‘void p<type>::f() [with type = int]’: 
x.cpp:26:9: required from here 
x.cpp:19:13: error: invalid use of unary ‘*’ on pointer to member 
    cout << *q; 
      ^

Jetzt kann ich keine weiteren Änderungen durchführen. Ich würde gerne wissen, ob der ursprüngliche Code nicht die Eigenschaften der Klasse zu schützen geschützt.

+0

'& a :: b 'ist die spezielle Syntax, um einen Zeiger zu einem Mitglied zu bilden. Sie können '& (a :: b)' verwenden, um einen einfachen Zeiger zu bilden. – Quentin

+0

@iammilind Alles [sieht gut aus] (http://coliru.stacked-crooked.com/a/a97f5232e5a04c86), sobald die Klammern hinzugefügt sind. – Quentin

+0

@Quentin, ja ich stehe korrigiert. Aber ich fühlte, dass das Ersetzen durch "(this -> b)" das Problem fleißiger löst. Und für dieses spezielle Problem gab es im verknüpften Duplikat keine Antwort. Ich habe die Frage erneut geschlossen.Ich bin mir nicht sicher, ob ich meine Antwort löschen soll, da sie auf das spezifische Problem abzielt. Also behalte es, indem du den Zweifeln zugute kommst. – iammilind

Antwort

2

Sie können nach wie vor mit protected: type *b; leben, wenn Sie unter der Zeile im Code ändern:

type **q = &a<type>::b; // `protected: b` is not accessible in this context 

zu

type **q = &(this->b); // we make sure that `protected: b` is accessed here 

In einem solchen Fall Sie behandeln tatsächlich b als geerbt protected Mitglied.


Warum this für den Zugriff auf Basisklasse zu benutzen?
Siehe: In a templated derived class, why do I need to qualify base class member names with "this->" inside a member function?


Ein anderer Weg

ursprünglich von @Quentin verbunden, unterhalb Beitrag, den Unterschied zwischen einem einfachen und Zeiger Zeiger auf ein Element schlägt vor:
Pointer-to-member confusion

In Ihrer ursprünglichen Frage haben Sie also versucht, einen Zeiger auf Membervariable zu bekommen le durch folgende Syntax:

&a<type>::b ==> int* a<int>::* 

während Sie wollten wahrscheinlich &(a<type>::b), die in einfachen int* führen würde.
So ist es eines der Notebook-Beispiele, die die Vorteile von Klammern an der richtigen Stelle zeigen! :-)

Verwandte Themen