C++ - Verdecken einer virtuellen Funktion

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

C++ - Verdecken einer virtuellen Funktion

Beitrag von Spiele Programmierer »

Ich bin heute über ein überraschendes seltenes Problem in C++ gestolpert, wofür ich früher in C# eine einfache Lösung gehabt hätte.
Und zwar geht es darum eine virtuelle Funktion nicht zu überschreiben sondern zu verdecken. Konkret soll folgendes möglich sein...

Code: Alles auswählen

class A
{
public:
    virtual std::uint64_t SomeFunction();
};
class B : public A
{
public:
    std::uint32_t SomeFunction(); //<-Zu beachten: Anderer Rückgabetyp.
    //Kein Ersatz in der VTable. Gibt es eine Instanz vom Typ "B" die in den Typ "A" gecastet ist,
    //soll immernoch die Implementierung von "SomeFunction" in der Basisklasse "A" aufgerufen werden.
};
In C# war das kein Problem, einfach die zweite Funktion in "B" mit "new" kennzeichnen. Gibt es eine Möglichkeit in C++ diese Funktionalität zu erreichen? Einfach auf die naive Weise, wie der Code oben, führt zur Fehlermeldung... "error C2555: 'B::SomeFunction': Der überschreibende virtuelle Funktionsrückgabetyp unterscheidet sich und ist keine 'covariant' von 'A::SomeFunction"
Der Compiler will offensichtlich die Funktion trotz unterschiedlichen Rückgabetyp überschreiben, was natürlich nicht klappt.
Zuletzt geändert von Spiele Programmierer am 06.10.2014, 17:53, insgesamt 1-mal geändert.
Helmut
Establishment
Beiträge: 237
Registriert: 11.07.2002, 15:49
Wohnort: Bonn
Kontaktdaten:

Re: C++ - Verschatten einer virtuellen Funktion

Beitrag von Helmut »

Das geht nicht. Überladene Funktionen dürfen sich nicht ausschließlich im Rückgabetyp unterscheiden.
Wofür brauchst du das denn?
Benutzeravatar
Jonathan
Establishment
Beiträge: 2661
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: C++ - Verschatten einer virtuellen Funktion

Beitrag von Jonathan »

Na, du könntest statt RÜckgabewert einen Zeiger oder eine Referenz übergeben um das Ergebnis zu bekommen. Das ist natürlich nicht so schön in der Benutzung, aber wenn du wirklich dringend das Verhalten brauchst, ist es natürlich eine Lösung.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: C++ - Verschatten einer virtuellen Funktion

Beitrag von Spiele Programmierer »

Ich will es auch nicht überladen. Ich will praktisch für "B" genau das Verhalten das es gäbe, wenn kein "virtual" in "A" angegeben wäre. Die Funktion in A ist dann einfach verdeckt. Nicht überladen und auch nicht überschrieben. Das "virtual" ist leider für weitere abgeleiteten Klassen notwendig.

In dem Fall geht es tatsächlich eher um die Benutzung, theoretisch könnte ich der Methode auch einen anderen Namen geben, das fände ich allerdings nicht so nett und ich bin etwas schockiert, dass es dafür tatsächlich keine (offensichtliche) Lösung gibt.

Zur Verwendung:
Es geht einfach darum, dass meine Basisklasse eine Funktionalität anbietet, die technisch 64Bit Integer voraussetzt. (Noch genauer gesagt geht es um meine Stream-Klasse). Nun gibt es eine davon abgeleitete Klasse, die selbst Prinzip bedingt maximal Werte im Bereich von "size_t" zurückgibt. Um einige unnötige Casts bzw. Warnungen im 32Bit Build zu sparen, war meine Idee, einfach die Funktionen mit solchen zu verdecken, die das selbe tun, aber direkt den Typ zurückgeben.

EDIT:
Jonathan hat mich auf eine andere Idee gebracht. Scheint zu funktionieren, vielleicht gibt es aber auch eine direktere Lösung. (Getestet mit Clang & MSVC)

Code: Alles auswählen

class A
{
public:
    virtual std::uint64_t SomeFunction();
};
class B : public A
{
public:
    std::uint32_t SomeFunction(int Unused = 0); //Durch den Parameter versucht der Compiler nicht mehr zu überschreiben...
};
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: C++ - Verdecken einer virtuellen Funktion

Beitrag von dot »

Code: Alles auswählen

class A
{
protected:
  virtual std::uint64_t SomeFunction64() { ... }

  friend std::uint64_t SomeFunction(A& a)
  {
    return a.SomeFunction64();
  }
};

class B : public A
{
private:
  std::uint32_t SomeFunction32() { ... }

  friend std::uint32_t SomeFunction(B& b)
  {
    return b.SomeFunction32();
  }
};


A& a = ...;
B b;

auto x = SomeFunction(a); // calls 64 bit version
auto y = SomeFunction(b); // calls 32 bit version
Benutzeravatar
dot
Establishment
Beiträge: 1746
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: C++ - Verdecken einer virtuellen Funktion

Beitrag von dot »

Oder per nonvirtual Interface Pattern:

Code: Alles auswählen

class A
{
protected:
  virtual std::uint64_t SomeFunction64() { ... }
  
public:
  std::uint64_t SomeFunction()
  {
    return SomeFunction64();
  }
};

class B : public A
{
private:
  std::uint32_t SomeFunction32() { ... }
  
  std::uint64_t SomeFunction64()
  {
    return SomeFunction32();
  }
  
public:
  std::uint32_t SomeFunction()
  {
    return SomeFunction32();
  }
};
Spiele Programmierer
Establishment
Beiträge: 426
Registriert: 23.01.2013, 15:55

Re: C++ - Verdecken einer virtuellen Funktion

Beitrag von Spiele Programmierer »

Danke, auch gute Idee.
Werde ich dann wohl so machen. :)
Antworten