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 soll foo::operator()(double) -> double einen interpolierten Wert zurückgeben.

    Edit:
    Also ich könnte je nach verwendetem Konstruktor eine Variable bool standard initialisieren und operator fragt dann z.B. bei seinem Aufruf if(standard == false / true) , aber das wäre bei jedem Funktionsaufruf etwas arg umständlich, da noch eine if -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.


  • Mod

    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.


  • Mod

    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(); }
    };
    

    http://ideone.com/HV5Drc

    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.


Log in to reply