Forum: Compiler & IDEs [c++] Zugriff auf einzelne Methoden der Basisklasse erlauben


von Leo B. (luigi)


Lesenswert?

Hallo zusammen,

ich stehe gerade an einer Art Luxus-Problem und frage mich ob ihr mir 
helfen könnt dieses zu lösen.

Folgender Aufbau:
1
#include <iostream>
2
3
using namespace std;
4
class Base
5
{
6
public:
7
    void fooBase() {  cout << "void A::fooBase()" << endl;  }
8
    void fooBase( char c ) {  cout << "void A::fooBase( '" << c <<"' )" << endl;  }
9
    void barBase() {  cout << "void A::barBase()" << endl;  }
10
};
11
12
13
class Derived : private Base // von Base wird privat vererbt!
14
{
15
public:
16
    using Base::fooBase;     // auf Base::fooBase() soll der zugriff erlaubt sein
17
18
    void fooDrvd() {  cout << "void B::fooDrvd()" << endl;  }
19
20
};
21
22
int main(int /*argc*/, char */*argv[]*/)
23
{
24
    Derived d;
25
26
    d.fooBase();         // <- benötigter Zugriff
27
    d.fooBase( 'b' );    // <- soll verboten werden
28
    // d.barBase();      // <- gewollt nicht erlaubt
29
30
    return 0;
31
}

So mein Problem ist nun, dass ich auf fooBase() eines Derived-Objekts 
zugreifen muss/möchte. Den Zugriff auf fooBase( char c ) würde ich 
allerdings gerne unterbinden. Mittels "using ..." kann ich aber offenbar 
nur den Zugriff auf alle Methoden der Basisklasse mit diesem Namen 
freigeben.
Eine Weg der mir einfallen würde wäre eine eigene Methode
1
void Derived::fooBase() { Base::fooBase(); }
zu schreiben. Das finde ich allerdings ziemlich unschön und vermutlich 
auch nicht so performant. Es wäre mir lieber direkt auf die 
Basisklassen-Methode zugreifen zu können.
Fällt euch dazu irgendwas ein?


Letztlich ist es ja nicht schlimm, wenn auch die unerwünschte Methode 
erreichbar ist, aber vielleicht gibt es ja auch einen weg der genau das 
erlaubt was ich mir vorstelle. Würde mich freuen, in dieser ecke wieder 
was lernen zu können, da ich irgendwie schon häufiger auf solche 
Probleme gestoßen bin, aber noch nie eine schöne Lösung gefunden habe.

Vielen Dank schonmal
lg Leo


PS: Falls ihr euch fragt, warum ich das unbedingt in der abgeleiteten 
Klasse lösen möchte und nicht einfach die entsprechenden Methoden in der 
Basisklasse als private deklariere und dann public vererbe: Auf die 
Basisklasse habe ich keinen Zugriff. Die Existiert so schon. ;)

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Mir fällt momentan nur eine immens blöde Lösung ein, nämlich die Methode 
in der abgeleiteten Klasse zu überschreiben aber nicht zu 
implementieren. Dann verhindert der Linker, dass du sie aufrufst. :D

von Dr. Sommer (Gast)


Lesenswert?

Leo B. schrieb:
> Das finde ich allerdings ziemlich unschön und vermutlich
> auch nicht so performant
Das ist kein Problem, halbwegs schlaue Compiler optimieren das weg. 
Dafür kannst du es auch inline machen. Funktionen die einfach nur eine 
andere Funktion aufrufen sind üblich und nicht per se hässlich. 
Jedenfalls weniger hässlich als private Dinge die aufrufbar sind.

von Protected (Gast)


Lesenswert?

..ist das was du willst mit dem Schlüsselwort "protected" lösbar?
ist von außen gesehen sowas wie private, innerhalb der 
Ableitungshirarchie aber praktisch public.

von Leo B. (luigi)


Lesenswert?

Danke euch dreien. Protected ist mir bekannt, aber 1. ist die 
Basisklasse für mich ja nicht editierbar und 2. möchte ich die 
entsprechenden Methoden von "aussen" aufrufen können.

Aber das Stichwort inline hat mich eigentlich auf den richtigen Gedanken 
gebracht. Wenn eine Inline-Funktion oder Methode einzig eine andere 
Funktion oder Methode aufruft, dürfte sie im beim Compilieren am Ende 
transparent werden und keinerlei Nachteile bringen.
Das gefällt mir ganz gut. Und den Code machts auch nicht 
unübersichtlicher.
Danke euch!

von Protected (Gast)


Lesenswert?

Je nach dem, was für dich übersichtlicher ist, kannst du in der 
Public-Sektion die Überladugnen erwähnen, die du durschschleifen 
möchstest, ODER

du kannst alle Überladungen per Using public machen und nur die 
ungewünschten Überladungen sperren, indem du sie per "private" 
durchschleifst.

 Je nach dem, ob du prinzipiell alles erlauben willst, bis auf etwas 
Bestimmtes, ODER ob du Prinzipiell alles unterbinden willst, bis auf 
etwas Bestimmtes.



class Base
{
public:
  void A(void) { return; }
  void A(int a) { return; }
  void B(void) {return; }
};

class Child1_InhibitsOnly_A_int: private Base
{
 private:
  void A(int a) { Base::A(a); }
 public:
  using Base::A;
  void X(void) { return; }
};

class Child2_AllowsOnly_A_void: private Base
{
 private:
  using Base::A;
 public:
  void A() { Base::A(); }
  void X(void) { return; }
};

von Sebastian V. (sebi_s)


Lesenswert?

Leo B. schrieb:
> Wenn eine Inline-Funktion oder Methode einzig eine andere
> Funktion oder Methode aufruft, dürfte sie im beim Compilieren am Ende
> transparent werden und keinerlei Nachteile bringen.

Inline zwingt den Compiler aber nicht dazu die Funktion tatsächlich zu 
inlinen. Allerdings sind inline Funktionen von der One-Definition-Rule 
ausgenommen, sodass diese Funktionen in Header Dateien definiert werden 
können und die Definition der Funktion in allen Compilation-Units 
bekannt ist. Dies ist natürlich eine Voraussetzung dafür, dass der 
Compiler die Funktion inlinen kann. Allerdings sind Memberfunktionen die 
innerhalb der Klassendefinition definiert werden bereits implizit 
inline, sodass du dir dort das Keyword sparen könntest.

von Sven (Gast)


Lesenswert?

Also alles was du in der Basisklasse deklarierst wird auch immer 
zugreifbar sein. Speziell wenn jemand einen Pointer auf die Basisklasse 
hält oder castet wird das immer möglich werden. Abhilfe kannst du nur 
schaffen, wenn du das aus der Basis protected machst oder dein Design so 
umstellst, das du es nicht benöitigst. Denn wenn solche Situationen 
auftreten, dann ist meist am Design etwas gammelig! Das ganze schreit 
danach, das du nicht ein Interface oder basis benötigst, sondern 
mehrere.

von Sebastian V. (sebi_s)


Lesenswert?

Sven schrieb:
> Also alles was du in der Basisklasse deklarierst wird auch immer
> zugreifbar sein.

Nicht bei private inheritance. Da wird effektiv verhindert, dass du 
Derived nach Base konvertierst oder auch einen Pointer oder Reference 
auf Derived zu Base konvertierst. Das kann unter anderem dann sinnvoll 
sein, wenn die Basisklasse ursprünglich nicht als Basisklasse ausgelegt 
war z.B. kein virtual Destructor besitzt.

: Bearbeitet durch User
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.