C++ Memberpointer auf Basisklasse konvertieren

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

C++ Memberpointer auf Basisklasse konvertieren

Beitrag von Xin » Mo Jul 29, 2013 10:21 pm

Moin!

Alle im Sommerloch verschwunden? ^^
Ich komme endlich mal wieder an den Rechner und stehe schon vor einem Problem:

Code: Alles auswählen

class Base
{
public:
  int a;
};

class Derived : public Base
{
public:
  int b;
};

class Wrapper
{
public:
  Derived derived;
};

int main( void )
{
  Derived Wrapper::*wd = &Wrapper::derived;
  Base    Wrapper::*wb = &Wrapper::derived;  // 23: error: invalid conversion from ‘Derived Wrapper::*’ to ‘Base Wrapper::*’ [-fpermissive]

  return 0;
}
Auch clang äußert sich nicht sonderlich gnädig zu dem Thema:

Code: Alles auswählen

in@trinity:~$ clang memberptr.cpp 
memberptr.cpp:22:23: error: cannot initialize a variable of type 'Base Wrapper::*' with an rvalue of type 'Derived Wrapper::*'
  Base    Wrapper::*  wb = &Wrapper::derived;  // 23: error: invalid conversion from ‘Derived Wrapper::*’ to ‘Base ...
                      ^    ~~~~~~~~~~~~~~~~~
1 error generated.
Ich möchte eine Funktion aufrufen, die einen (Base Wrapper::*) als Argument erhält.

Hat jemand einen Tipp, wie ich das C++ verklickert bekomme? ^^
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

GilbertDur
Beiträge: 105
Registriert: Fr Mär 01, 2013 10:31 am

Re: C++ Memberpointer auf Basisklasse konvertieren

Beitrag von GilbertDur » Di Jul 30, 2013 8:44 am

Ich habe keine Lösung für dein Problem, aber mal eine Frage zum Code. Ich habe das Konstrukt nämlich so noch nie gesehen.

Code: Alles auswählen

Derived Wrapper::*wd = &Wrapper::derived;
Was genau sagt die Zeile aus? Dass das, worauf *wd zeigt, zwingend ein Derived in der Wrapper-Klasse sein muss?

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: C++ Memberpointer auf Basisklasse konvertieren

Beitrag von Xin » Di Jul 30, 2013 9:28 am

GilbertDur hat geschrieben:Ich habe keine Lösung für dein Problem,
Ich habe jetzt eine Lösung mit der ich noch nicht zufrieden bin:

Code: Alles auswählen

class Base
{
 public:
   int a;
};

class Derived : public Base
{
  public:
    int b;
};

class Wrapper
{
  public:
    Derived derived;
};

void targetfunc( Base Wrapper::*memptr )
{
  // nothing to do
}

template< typename T, typename U >
void func( T U::*memptr )
{
  targetfunc( reinterpret_cast< Base U::* >( memptr ));
}

int main( void )
{
  Derived Wrapper::*wd = &Wrapper::derived;

  func( &Wrapper::derived );

  return 0;
}
Der reinterpret_cast erscheint mir noch nicht wirklich notwendig... der Compiler sieht das anders, also gut. Um den Memberpointer in eine andere Funktion zu bekommen, brauche ich nun das Template, was ich eigentlich auch eher unschön finde, was mir aber abnimmt, beim Aufruf von targetfunc den reinterpret_cast in den Funktionsaufruf zu packen.

GilbertDur hat geschrieben: aber mal eine Frage zum Code. Ich habe das Konstrukt nämlich so noch nie gesehen.

Code: Alles auswählen

Derived Wrapper::*wd = &Wrapper::derived;
Was genau sagt die Zeile aus? Dass das, worauf *wd zeigt, zwingend ein Derived in der Wrapper-Klasse sein muss?
Richtig.
Ein Derived in einer beliebigen Instanz einer Wrapper-Klasse um genau zu sein.

Das ist ein Methoden-, bzw. in dem Fall ein Memberpointer. Du zeigst nicht auf ein Derived, sondern auf die Position eines Derived innerhalb eines Wrapperobjekts. Der Pointer alleine zeigt also nur in Verbindung mit einem Wrapperobjekt auf etwas sinnvolles, entsprechend muss beides kombiniert werden.

Code: Alles auswählen

Wrapper w;
Wrapper pw = &w;

Derived d = w.*wd;  
d = pw->*wd;
Ich glaube, Methoden- und Memberpointer sind im Tutorial noch nicht drin und auch eher seltene Kost bei C++-Tutorials. Das ist auch eher etwas exotisches, aber es zeigt eben auch, was man mit C++ alles ausdrücken machen kann, auch wenn ich mit der Konvertierung von (Derived Wrapper::*) nach (Base Wrapper::*) anscheinend an die Grenzen von C++ stoße und mich mit reinterpret_cast<> darüber hinweg setzen muss.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

GilbertDur
Beiträge: 105
Registriert: Fr Mär 01, 2013 10:31 am

Re: C++ Memberpointer auf Basisklasse konvertieren

Beitrag von GilbertDur » Di Jul 30, 2013 7:11 pm

Xin hat geschrieben: Ich glaube, Methoden- und Memberpointer sind im Tutorial noch nicht drin und auch eher seltene Kost bei C++-Tutorials. Das ist auch eher etwas exotisches, aber es zeigt eben auch, was man mit C++ alles ausdrücken machen kann, auch wenn ich mit der Konvertierung von (Derived Wrapper::*) nach (Base Wrapper::*) anscheinend an die Grenzen von C++ stoße und mich mit reinterpret_cast<> darüber hinweg setzen muss.
Eindeutig. Habe ich noch in keinem C++ Buch oder Tutorial gesehen. Wie so oft hier im Forum: Wieder was gelernt. Ich hätte grundsätzlich auch einen Cast versucht, allerdings finde ich die immer etwas unschön. Ich wollte aber lieber erst verstehen, worum es eigentlich geht :)

Antworten