2 Stimmen

Zwei sehr ähnliche Klassen in C++ mit nur einer unterschiedlichen Methode: Wie soll man sie implementieren?

Ich habe zwei Klassen, die bis auf eine Methode fast identisch sind. Die Klassen haben den gleichen Datenteil und alle Mitgliedsfunktionen außer einer:

class A {
private:
  double data;
public:
  double calc(){
     return data*data;
  }
   double especific(){
     return 2.0*data;
  }
 }

und die zweite Klasse ist, abgesehen von der spezifischen Methode, identisch.

Insbesondere diese Mitgliedsfunktion benötigt alle Mitgliedsdaten zur Berechnung, so dass die Übergabe als Wert oder Referenz keine Option ist. Gibt es eine Möglichkeit, dies ohne eine Menge Code-Duplizierung zu implementieren? Entweder mit nur einer Klasse oder mit Vorlagen, aber nicht Vererbung (große Auswirkungen auf die Leistung).

Danke

EDITAR : Vielen Dank für die vielen Antworten. Die Strategie Muster kann in meinem Fall helfen, ich werde es versuchen und sehen, ob es funktioniert. Ich vermeide die virtuelle Vererbung wie die Pest, basierend auf einigen Tests, die ich in einem anderen Programm durchgeführt habe. Diese Routine wird überall aufgerufen werden, und die Leistung ist ein sehr wichtiger Faktor.

8voto

Omnifarious Punkte 52299

Das klingt nach einem Job für die Strategie-Muster . Er kann in diesem Fall als Vorlagenparameter implementiert werden. Oft wird er als Konstruktorparameter oder als Setter-Methode der Klasse implementiert, aber das würde Vererbung voraussetzen, um richtig zu funktionieren.

In diesem Fall etwas wie:

template <class SpecificStrategy>
class A {
 private:
    double data;
 public:
    double calc(){
       return data*data;
    }
    double especific() {
       return SpecificStrategy::especific(data);
    }
};

class DoubleStrategy {
   static double especific(double data) {
      return 2 * data;
   }
};
class TripleStrategy {
   static double especific(double data) {
      return 3 * data;
   }
};

Dann können Sie nachschlagen:

A<DoubleStrategy> x;
A<TripleStrategy> y;

x y y von völlig unterschiedlichen Typen sein, aber das ist in diesem Fall wohl nicht das, was Sie wollen.

Nun, meiner Meinung nach mit einer virtuellen Funktion und Vererbung ist der Weg zu gehen. Wie jemand anderes schon sagte, ist der Leistungsverlust nicht so groß. Allerdings gibt es Umstände, unter denen ich sehen könnte, dass es eine schlechte Idee wäre.

Wenn diese Klasse beispielsweise einen Vektor in einem Grafikpaket repräsentieren soll und Sie dieselbe Transformation für Millionen von Vektoren durchführen, dann könnte ich mir vorstellen, dass Sie nicht möchten, dass ein Aufruf einer virtuellen Funktion Teil des Codes ist, der die Transformation durchführt. In der Tat würden Sie Zeiger-Dereferenzen jeglicher Art vermeiden wollen, wenn es sich irgendwie vermeiden lässt.

2voto

pm100 Punkte 40532

Eine Basisklasse mit allen gemeinsamen Elementen haben und die beiden Klassen von ihr ableiten

Wie andere bereits festgestellt haben

a) Das ist genau das, wofür die Vererbung gedacht ist.

b) es gibt keinerlei Leistungsmehraufwand

c) es lauern nirgendwo böse Überraschungen

Viele Leute werden dies kommentieren und sagen "ah, aber was ist mit xxxx"; dies sind berechtigte Kommentare für fortgeschrittene und Eckfälle; nur werden Sie nichts davon tun, wenn Sie sich auf die Einfachheit dessen verlassen, was Sie verlangt haben.

2voto

Ade Miller Punkte 13246

Vielleicht verstehe ich den Sinn nicht, aber warum gibt es nicht eine Basisklasse, die alle gängigen Funktionen implementiert, und eine rein virtuelle especific() und diese dann erben und die Kindklassen implementieren lassen especific() nach Bedarf. Machen Sie die data Mitglied geschützt.

class BaseA 
{ 
protected: 
  double data; 
public: 
  double calc(){ 
     return data*data; 
  } 
   virtual double especific() = 0;
};

class A1 : BaseA
{
   double especific()
   {
     return data * 2;
   }
};

Was die enormen Auswirkungen der Vererbung auf die Leistung angeht... Ich denke, dies ist nicht wahrscheinlich, es sei denn, die Kosten für vtable Lookups ist signifikant im Vergleich zu der Arbeit, die in der Methode Körper getan, und Sie tun dies in einer engen Schleife, die die meisten Ihrer Anwendung Verarbeitung verbraucht.

2voto

T.E.D. Punkte 42630

Wenn Sie keine Mitglieder werden virtual und Ihre Klassen intelligent definieren, sollte es keinerlei Leistungseinbußen durch Vererbung .

Alles, was Vererbung bedeutet, ist "mache diese Klasse wie jene, aber mit diesem zusätzlichen Zeug". Das ist zur Laufzeit nicht anders, als wenn man dasselbe zweimal eingegeben hätte.

Ich nehme an, Sie könnten machen. eine Auswirkung auf die Leistung, indem im Konstruktor der übergeordneten Klasse ein Haufen unnötiger Dinge getan wird, die die untergeordneten Klassen nicht benötigen. Aber so dumm werden Sie nicht sein. Ich habe Vertrauen in dich.

2voto

InsertNickHere Punkte 3596

Warum überhaupt zwei Klassen? Wenn die Klassen dieselben Daten verwenden, können Sie beide Funktionen in einer Klasse implementieren.

class A {
private:
  double data;
public:
  double calc(){
     return data*data;
  }
   double especific(){
     return 2.0*data;
  }
   double eMoreSpecific() {
     return 23.0*data;
 }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X