Konstruktor bestimmt Verhalten von memberfunction
-
Hallo ihr Lieben,
ich habe auch mal wieder eine naive Frage: Ist es möglich über den zur Initialisierung verwendeten Konstruktor das Verhalten einer Memberfunction zu steuern?
Fall 1: Das Objekt
foo
wird über den Defaultconstructor initialisiert, dann soll z.B.foo::operator()(double) -> double
einfach 0.0 zurückgeben.Fall 2: Das Objekt
foo
wird mittels zweier Vektoren initialisiert, dann sollfoo::operator()(double) -> double
einen interpolierten Wert zurückgeben.Edit:
Also ich könnte je nach verwendetem Konstruktor eine Variablebool standard
initialisieren undoperator
fragt dann z.B. bei seinem Aufrufif(standard == false / true)
, aber das wäre bei jedem Funktionsaufruf etwas arg umständlich, da noch eineif
-Abfrage dazwischen zu klemmen - oder nicht?Gruß,
-- Klaus.
-
Ein Objekt, das sich je nach Konstruktoraufruf anders verhält? Das ist nicht ein Objekttyp, das sind zwei verschiedene! Mach zwei unterschiedliche Klassen draus. Wenn das nicht geht, sag wieso und ich zeige dir, wie man Vererbung nach aussen hin unsichtbar macht.
-
binsehrlieb schrieb:
Wenn das nicht geht, sag wieso und ich zeige dir, wie man Vererbung nach aussen hin unsichtbar macht.
Weil ich z.B. einen Vektor der gegebenen Klasse füllen möchte, da kann ich nicht einfach zwei Klassen drauß machen.
Gruß,
-- Klaus.
-
aber das wäre bei jedem Funktionsaufruf etwas arg umständlich, da noch eine if-Abfrage dazwischen zu klemmen - oder nicht?
Wie willst du sonst eine Unterscheidung treffen? Natürlich ist das in Ordnung.
Du könntest auch als Bedingung die Größe der internen Vektoren abfragen, mittels
empty()
(die ja beim zweiten Konstruktor dann gefüllt werden).
-
Edit:... Überlesen.
-
freaky schrieb:
Was spricht gegen diese einfache Methode?
Nichts, aber die hat er doch selbst schon in Erwägung gezogen.
-
Die vermutlich schnellere Variante ist ein if/else, die etwas flexiblere wäre Vererbung+type erasure:
class speziell { struct allg { virtual double get() =0; }; struct einfach0 : allg { double get() { return 0.0; } }; struct interpoliert : allg { interpoliert(double x) : x(x) {} double x; double get() { return x; } }; std::unique_ptr<allg> data; public: speziell() : data(new einfach0) {} speziell(double x) : data(new interpoliert(x)) {} double get() { return data->get(); } };
Um die Indirektion wirst du nicht herumkommen, ausser du schaffst es irgendwie, die 0 als Spezialfall der Interpolation hinzubekommen. Sehr wahrscheinlich ist das if bei dir am besten geeignet, aber ich wollte dir zumindest noch eine Alternative zeigen.
-
Einfach in einem zusätzlichem double denWert speichern, denn der operator zurückliefert?!
-
Nathan schrieb:
Einfach in einem zusätzlichem double denWert speichern, denn der operator zurückliefert?!
Wie meinen?
Dann komme ich aber nicht drum herum abzufragen, ob ich einen interpolierten Wert möchte oder diesen zusätzlich gespeicherten Wert?
Gruß,
-- Klaus.
-
ich werfe hier mal einfach das wort pimpl-idiom in den raum (auch wenn das für den beschriebenen anwendungsfall deutlich overkill ist).
beispiel:
#include <memory> #include <vector> struct foo_impl_interface { virtual double fn(double) const = 0; }; struct foo_impl_zero : public foo_impl_interface { virtual double fn(double) const { return 0.0; } }; template<class IteratorType> struct foo_impl_interpol : public foo_impl_interface { IteratorType begin1, end1; IteratorType begin2, end2; foo_impl_interpol(IteratorType begin1, IteratorType end1, IteratorType begin2, IteratorType end2) : begin1(begin1), end1(end1), begin2(begin2), end2(end2) { } // wenn du die beiden vektoren für die interpolation doch nicht brauchst, das hier oben einfach weglassen virtual double fn(double) const { // hier den teil mit der interpolation einfügen return 1.0; } }; class foo { std::unique_ptr<foo_impl_interface> impl; public: foo() : impl(new foo_impl_zero) { } foo(std::vector<double> const& vec1, std::vector<double> const& vec2) : impl(new foo_impl_interpol<std::vector<double>::const_iterator>(vec1.begin(), vec1.end(), vec2.begin(), vec2.end())) { } double operator() (double val) const { return this->impl->fn(val); } }; int main() { foo a; std::vector<double> lhs, rhs; foo b(lhs, rhs); }
-
Klaus82 schrieb:
Nathan schrieb:
Einfach in einem zusätzlichem double denWert speichern, denn der operator zurückliefert?!
Wie meinen?
Dann komme ich aber nicht drum herum abzufragen, ob ich einen interpolierten Wert möchte oder diesen zusätzlich gespeicherten Wert?
Gruß,
-- Klaus.Musste dann aber nur einmal im Konstruktor machen und nicht bei jedem Aufruf von operator double.
BTW: operator type sind nicht grad das Gelbe vom Ei.
-
@Klaus82
Wie heisst deine Klasse? Und was ist ihre Aufgabe? Was stellt sie dar?Wenn du diese Fragen beantwortest, dann ergibt sich das Design meist ganz von selbst.