Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Dynamisches Array aus Klasse mit statischem Array vererben

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
09.11.2009, 10:38 Uhr
FrEEzE2046



Hallo,

der Titel ist schlecht formuliert. Ich habe eine Klasse die ein statisches Array enthält. Einige Funktionen dieser Klasse greifen auf das Array zu. Ich brauche jedoch auch noch eine Variante der Klasse die ein dynamisches Array verwaltet. Der Zugriff auf das Array ist gleich, da in C++ sowieso jedes Array ein Pointer auf das erste Element ist.

Ich würde daher gerne die Funktionen der statischen Klasse in der der dynamischen Klasse verwenden. Das funktioniert aber nicht, da die Methoden immer noch auf das statische Element zugreifen.

Es sei dazu gesagt, dass ich hier extra ein Beispiel programmiert habe, dass keinen Sinn für sich selbst hat.

Die einzige Lösung die mir einfällt ist es einen Pointer von dem Typ zu deklarieren und den schon im Interface zu implemenentieren. Ich wollte aber eigentlich Redundanz so weit wie möglich vermeiden. Gibt es da noch einen besseren Weg?




C++:
template<typename _Ty>
class Interface
{
public:
    virtual operator _Ty* (void) = 0;

    virtual _Ty summe(void) = 0;
};


template<typename _Ty, size_t _n>
class Statisch : public Interface<_Ty>
{
private:
    enum { _elCount = _n };
    _Ty _array[_n > 0 ? _n : 1];

protected:
    enum { _elSize = sizeof(_Ty) };

public:
    Statisch(void) {
        memset(this->_array, 0, _n * _elSize);
    }

    virtual _Ty summe(void) override
    {
        _Ty Result = 0;
        for( int i = 0; i < _elCount; i++ )
            Result += this->_array[i];
        return Result;
    }

    virtual operator _Ty* (void) override {
        return this->_array;
    }
};


template<typename _Ty>
class Dynamisch : public Statisch<_Ty, 0>
{
private:
    _Ty* _array;

public:
    Dynamisch(size_t n) : _array(new _Ty[n]()) {}

    ~Dynamisch(void) {
        delete[] this->_array;
    }
};
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
09.11.2009, 11:25 Uhr
ao

(Operator)


Dringender Verdacht auf Designfehler

Eine Ableitung drückt eine "Ist-ein"-Beziehung zwischen den betreffenden Klassen aus, in diesem Fall also "Dynamisch ist ein Statisch". Das ist schon vom Wortsinn her ein Widerspruch.

Deine Ableitungshierarchie verspricht etwas, das die Wirklichkeit nicht hält, und das spricht dafür, dass hier keine Ableitung hingehört. Besser wäre vielleicht, beide Klassen (Dynamisch und Statisch) von Interface ableiten und getrennt zu implementieren.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
09.11.2009, 11:43 Uhr
~FrEEzE2046
Gast



Zitat von ao:
Dringender Verdacht auf Designfehler

Eine Ableitung drückt eine "Ist-ein"-Beziehung zwischen den betreffenden Klassen aus, in diesem Fall also "Dynamisch ist ein Statisch". Das ist schon vom Wortsinn her ein Widerspruch.

Deine Ableitungshierarchie verspricht etwas, das die Wirklichkeit nicht hält, und das spricht dafür, dass hier keine Ableitung hingehört. Besser wäre vielleicht, beide Klassen (Dynamisch und Statisch) von Interface ableiten und getrennt zu implementieren.


Erst ein mal danke für deine Antwort.

Ja,
diesen Weg habe ich ja bereits angesprochen. Er wäre auf jeden Fall der, der mich zum Ziel führt. Aber wie in diesem einfachen Beispiel habe ich in beiden Klassen dann Funktionen die 1:1 gleich sind. Sie enthalten die selbe Logik, den selben Code und greifen ja auch gleich auf das array zu.

In C/C++ macht es ja keinen Unterschied, ob das array statisch oder dynamisch erzeugt worden ist; wenn man es ansprechen will ist es immer ein Pointer auf das erste Element.
Also habe ich wohl keine Chance dass so zu lösen und muss Redundanz in Kauf nehmen?
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
09.11.2009, 12:04 Uhr
ao

(Operator)


Code-Redundanz ist (fast) immer schlecht. Du könntest eine weitere Klasse einführen, die nur die relevanten Implementierungen enthält. Etwa so (ohne Test hingekritzelt):


C++:
template<typename _Ty>
class Interface
{
public:
    virtual operator _Ty* (void) = 0;

    virtual _Ty summe(void) = 0;
};

//  eine Impl.-Klasse, die die Funktionen statisch implementiert
template<typename _Ty, size_t _n>
class ArrayImpl
{
public:
    
    //  Hier steckt an zentraler Stelle das Knowhow,
    //  wie eine Array-Summe berechnet wird
    static _Ty summe (_Ty * array, size_t len)
    {
        _Ty result = 0;
        for (int i = 0; i < len; i++)
        {
            result += array[i];
        }
        return result;
    }
    
};

// Realisierung eines statischen Arrays
template<typename _Ty, size_t _n>
class Statisch : public Interface<_Ty>
{
private:
    enum { _elCount = _n };
    _Ty _array[_n > 0 ? _n : 1];
    
protected:
    enum { _elSize = sizeof(_Ty) };

public:

    //  Konstruktion eines statischen Arrays
    Statisch(void)
    {
        memset (_array, 0, sizeof (_array));        
    }

    //  Summe über das Array: ArrayImpl aufrufen
    virtual _Ty summe(void)
    {
        return ArrayImpl::summe (_array, _n);
    }

};

// Realisierung eines dynamischen Arrays

template<typename _Ty>
class Dynamisch : public Interface<_Ty>
{
private:
    _Ty* _array;
    size_t len;
    
public:

    //  Konstruktion eines dynamischen Arrays
    //  Unterschied zum statischen: Die Länge zur Compilezeit unbekannt
    //  und wird daher zur Laufzeit festgehalten.
    Dynamisch(size_t n)
    : _array(new _Ty[n]())
    , len (n)
    {
        memset(_array, 0, sizeof (*_array) * n);
    }

    ~Dynamisch(void) {
        delete[] this->_array;
    }
    
    //  Summe über das Array: ArrayImpl aufrufen.
    virtual _Ty summe(void)
    {
        return ArrayImpl::summe (_array, len);
    }
};


Dieser Post wurde am 09.11.2009 um 12:05 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
09.11.2009, 12:52 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


naja wärs dann nicht einfacher das ganze andersrum zu machen?

also

"Ein statisches array IST ein dynamisches array mit fester größe"

das erschlägt doch dann alles?
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
09.11.2009, 12:58 Uhr
FrEEzE2046



Naja, das leichteste wäre es wohl, wenn man in Statisch auch ein dynamisches Array anlegt und ihm eine feste Größe gibt (wie du schon sagtest).

Dann könnten alle Funktionen gleich bleiben. Die Statisch Klasse würde dann aber nicht mehr alle Elemente auf dem Stack, sondern durch das array auch im Heap haben.


Ganz nebenbei sorgt das static in der ArrayImpl Klasse gleich dafür, dass mit thread-safe nicht mehr viel los ist.

Dieser Post wurde am 09.11.2009 um 13:02 Uhr von FrEEzE2046 editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
09.11.2009, 13:27 Uhr
ao

(Operator)



Zitat von FrEEzE2046:
Ganz nebenbei sorgt das static in der ArrayImpl Klasse gleich dafür, dass mit thread-safe nicht mehr viel los ist.

Wieso das? ArrayImpl hat nur eine statische Methode, aber keine statischen Daten. Alle Daten, mit denen die Methode arbeitet, stammen aus dem Kontext des Aufrufers. Threadsicherheit ist also gegeben.


Zitat von FloSoft:
"Ein statisches array IST ein dynamisches array mit fester größe"


Tz tz tz, du kleiner Schelm!

Ein Anwender setzt ein statisches Array doch gerade dann ein, wenn er teure new-Aktionen vermeiden will. Dieses "Statische" Array ist aber in Wahrheit ein dynamisches mit hart einkompilierter Länge - vereint also aus beiden Welten die Nachteile.

Dieser Post wurde am 09.11.2009 um 13:29 Uhr von ao editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
09.11.2009, 14:53 Uhr
FrEEzE2046




Zitat von ao:

Zitat:
Ganz nebenbei sorgt das static in der ArrayImpl Klasse gleich dafür, dass mit thread-safe nicht mehr viel los ist.

Wieso das? ArrayImpl hat nur eine statische Methode, aber keine statischen Daten. Alle Daten, mit denen die Methode arbeitet, stammen aus dem Kontext des Aufrufers. Threadsicherheit ist also gegeben.


Entschuldige, ohne Erklärung hast du recht. Bei mir (in meinm echten Code den ich hier aus rechtlichen Gründen nicht posten kann) wäre die Thread-Sicherheit gefährdet; bekomme ich aber auch hin.


Zitat von ao:
Dieses "Statische" Array ist aber in Wahrheit ein dynamisches mit hart einkompilierter Länge - vereint also aus beiden Welten die Nachteile.


Genau dass meinte ich ja und ist der Grund, warum ich meine Lösung so anstrebte wie oben. Es kommt da nämlich der Punkt wo man sich fragen muss, ob ein statisches Array überhaupt noch Sinn macht. Ich meine zwar trotzdem ja, da andere Klassen und Funktionen bei diesem Typ nicht überprüfen müssen, ob sich die Länge geändert hat; es ist jedoch trotzdem keine perfekte Lösung.

Dieser Post wurde am 09.11.2009 um 16:49 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: