Wie setze ich das mit STL und Vererbung um?



  • Hallo.

    Ich möchte gerne folgendes machen:

    Es gibt eien Basisklasse Object.
    Sie wird von StatObject und DynaObject geerbt.
    Nun möchte ich gerne einen Vector (später wirds ne M-Map) machen, der beides aufnehmen kann.
    Deswegen dachte ich, dass man eine Liste von (Object)en machen könnte...
    Naja, diesbezüglich habe ich ein Testprogramm gemacht:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
    };
    
    class B
    {
    public:
        int a;
    };
    
    typedef vector<A>           vecs;
    typedef vector<A>::iterator vecs_it;
    
    int main()
    {
        B bla;
        bla.a = 100;
    
        vecs v;
        v.insert((A*)&bla);
    
        getchar();
    
        return 0;
    }
    

    Naja, er bricht ab...
    Unbehanddelete Ausnahme...
    Er springt in XMEMORY:
    [cpp]
    // xmemory internal header (from <memory> )

    #if _MSC_VER > 1000
    #pragma once
    #endif

    #ifndef _XMEMORY_
    #define _XMEMORY_
    #include <cstdlib>
    #include <new>

    #ifdef _MSC_VER
    #pragma pack(push,8)
    #endif /* _MSC_VER /
    #include <utility>
    #ifndef _FARQ /
    specify standard memory model */
    #define _FARQ
    #define _PDFT ptrdiff_t
    #define _SIZT size_t
    #endif
    #define _POINTER_X(T, A) T _FARQ *
    #define _REFERENCE_X(T, A) T _FARQ &
    _STD_BEGIN
    // TEMPLATE FUNCTION _Allocate
    template<class _Ty> inline
    _Ty _FARQ *_Allocate(_PDFT _N, _Ty _FARQ 😉
    {if (_N < 0)
    _N = 0;
    return ((_Ty _FARQ *)operator new(
    (_SIZT)_N * sizeof (_Ty))); }
    // TEMPLATE FUNCTION _Construct
    template<class _T1, class _T2> inline
    void _Construct(_T1 _FARQ *_P, const _T2& _V)
    *{new ((void _FARQ )_P) _T1(_V); }
    // TEMPLATE FUNCTION _Destroy
    template<class _Ty> inline
    void _Destroy(_Ty _FARQ *_P)
    {_DESTRUCTOR(_Ty, _P); }
    inline void _Destroy(char _FARQ *_P)
    {}
    inline void _Destroy(wchar_t _FARQ *_P)
    {}
    // TEMPLATE CLASS allocator
    template<class _Ty>
    class allocator {
    public:
    typedef _SIZT size_type;
    typedef _PDFT difference_type;
    typedef _Ty _FARQ *pointer;
    typedef const _Ty _FARQ *const_pointer;
    typedef _Ty _FARQ& reference;
    typedef const _Ty _FARQ& const_reference;
    typedef _Ty value_type;
    pointer address(reference _X) const
    {return (&_X); }
    const_pointer address(const_reference _X) const
    {return (&_X); }
    pointer allocate(size_type _N, const void 😉
    {return (_Allocate((difference_type)_N, (pointer)0)); }
    char _FARQ *_Charalloc(size_type _N)
    {return (_Allocate((difference_type)_N,
    (char _FARQ *)0)); }
    void deallocate(void _FARQ *_P, size_type)
    {operator delete(_P); }
    void construct(pointer _P, const _Ty& _V)
    {_Construct(_P, _V); }
    void destroy(pointer _P)
    {_Destroy(_P); }
    _SIZT max_size() const
    {_SIZT _N = (_SIZT)(-1) / sizeof (_Ty);
    return (0 < _N ? _N : 1); }
    };
    template<class _Ty, class _U> inline
    bool operator==(const allocator<_Ty>&, const allocator<_U>&)
    {return (true); }
    template<class _Ty, class _U> inline
    bool operator!=(const allocator<_Ty>&, const allocator<_U>&)
    {return (false); }
    // CLASS allocator<void>
    template<> class _CRTIMP allocator<void> {
    public:
    typedef void _Ty;
    typedef _Ty _FARQ *pointer;
    typedef const _Ty _FARQ const_pointer;
    typedef _Ty value_type;
    };
    _STD_END
    #ifdef _MSC_VER
    #pragma pack(pop)
    #endif /
    _MSC_VER */

    #endif /* _XMEMORY_ */[/cpp]
    Bei der fett markierten Zeile ist bei mir der gelbe Pfeil, wie er für MS VC 6.0 typisch ist, also da ist ein problem...

    Najut, also wie kann ich mein Konzept verwirklichen, oder soll ich eine Alternative ergreifen, wenn ja, welche?

    MfG MAV



  • nicht den C Cast nehmen, der kümmert sich nämlich nicht um (alle) C++ Regeln.
    und nicht insert, sondern push_back (bei vector)
    einfach
    vecs.push_back (&bla);
    oder wenn du unbedingt casten willst (was aber nicht notwendig ist)
    nimm static_cast



  • statt vector<A> muss du mit vector<A*> arbeiten (muss dich dann aber um das delete kmmern), was sehr gut möglich ist vector<boost::shared_ptr<A> > (boost::shared_ptr gibt auf www.boost.org))



  • Hallo. 🙂

    [EDIT6]

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
        bool classtype;
    };
    
    class B : public A
    {
    public:
        int a;
    };
    
    typedef vector<A*>           vecs;
    typedef vector<A*>::iterator vecs_it;
    
    int main()
    {
        B bla;
        bla.a = 100;
    
        vecs v;
        vecs_it vit;
        v.push_back(&bla);
    
        for(vit = v.begin(); vit != v.end();)
        {
            B* temp;
            temp = reinterpret_cast<B*>(*vit++);
            cout << temp->a;   
        }
    
        getchar();
    
        return 0;
    }
    

    Der Code funktioniert jetzt endlich!
    Ohne Konvertierung sagt der aber, dass A* nicht in B* konvertiert werden kann, braucht reinterpret_cast blablabla...
    Naja, so klappt eigentlich alles, 100 wird ausgegeben. 🙂
    Wie immer frage ich, ob das so i.O. ist.
    Gibt es eine bessere Lösung?
    habe ich irgendwas missbraucht oder unsauber geproggt?
    Wär nett, wenn mich jemand auklären könnte. 🙂
    [EDIT7]
    Hm, außerdem hab ich die Instanzen ja net lebenslang im Speicher und static ist IMHO net so fein, oder?
    [EDIT8]
    @Dimah:
    Nagut, ich glaube jetzt wirklich nicht, dass du das so gemeint hast, wie ich es geschrieben habe, wäre nett, du könntest mir den kleinen Code umschreiben oder einen Minibeispielcode geben? *vorsichtig frag*

    Danke schonmal!

    MfG MAV

    [ Dieser Beitrag wurde am 11.05.2003 um 09:58 Uhr von Mis2com editiert. ]



  • *push* mit Verlaub



  • also wenn du dir 100% sicher bist das pointer auf A auf ein B zeigt dann kanns du static_cast benutzen
    wenn du dir dessen nicht sicher bist muss du mit dynamic_cast arbeiten, dazu muss aber midestenz eine virtuele funktion vorhanden sein

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
        bool classtype;
        virtuel ~A() {};
    };
    
    class B : public A
    {
    public:
        int a;
    };
    
    typedef vector<A*>           vecs;
    typedef vector<A*>::iterator vecs_it;
    
    int main()
    {
        B bla;
        bla.a = 100;
    
        vecs v;
        vecs_it vit;
        v.push_back(&bla);
    
        for(vit = v.begin(); vit != v.end();)
        {
            if(B * temp = dynamic_cast<B*>(*vit++))
                cout << temp->a;   
        }
    
        getchar();
    
        return 0;
    }
    

    wenn das A doch kein B war wird NULL zurück gegeben



  • Hallo. 🙂

    Also A ist entweder B oder C.
    Es gibt also zwei Klassen, die von A abgeleitetet sind, und eine von beiden kann das sein. 🙂
    Deswegen auch der bool, um zu überprüfen was genau das ist. ^^
    Kann man effektiver überprüfen welche Klasse das genau ist, oder ist das sonst mit dem bool in Ordnung? 🙂

    Danke jedenfalls für den Code und insgesamt. 🙂

    [EDIT]

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
    public:
        bool classtype;
    protected:
        virtual ~A() {};
    };
    
    class B : public A
    {
    public:
        int a;
    };
    
    typedef vector<A*>           vecs;
    typedef vector<A*>::iterator vecs_it;
    
    int main()
    {
        B bla;
        bla.a = 100;
    
        vecs v;
        vecs_it vit;
        v.push_back(&bla);
    
        for(vit = v.begin(); vit != v.end();)
        {
            if(B * temp = dynamic_cast<B*>(*vit++))
                cout << temp->a;   
        }
    
        getchar();
    
        return 0;
    }
    

    So, der Code hatte einige Minifehlerchen...
    Jedenfalls hab ich dir korrigiert, aber jetzt: Unbehandelte Ausnahme 😮

    MfG MAV

    [ Dieser Beitrag wurde am 11.05.2003 um 15:04 Uhr von Mis2com editiert. ]



  • Außerdem soll der Code auch nicht eine direkte Verbindung zu der Variable haben, also durch Adresse, weil, wenn das Teil im Gesäß ist, also futschikato, weil der Gültigkeitsbereich alle ist, wäre es ja raus aus dem array. 😞
    Und alles zu statisieren ist doof, oder? 😞

    MfG MAV

    [ Dieser Beitrag wurde am 11.05.2003 um 17:28 Uhr von Mis2com editiert. ]



  • #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
    public:
        bool classtype;
    protected:
        virtual ~A() {};
    };
    
    class B : public A
    {
    public:
        int a;
    };
    
    typedef vector<A*>           vecs;
    typedef vector<A*>::iterator vecs_it;
    
    int main()
    {
        B bla;
        bla.a = 100;
    
        vecs v;
        vecs_it vit;
        v.push_back(&bla);
        bla.a = 200;
        v.push_back(&bla);
    
        for(vit = v.begin(); vit != v.end();)
        {
            if(B* temp = static_cast<B*>(*(vit++)))
                cout << temp->a;   
        }
    
        getchar();
    
        return 0;
    }
    

    Das geht jetzt...

    Aber ich will verdammt nochmal keine Adressen so angebem, dass ich nach dem Beenden der Objekte Speicherlekcks habe, ist doch Mist...
    In dem Fall wird hier z.B. 200200 ausgegeben. 😞

    PS: Und was meinst du mit dem delete? Im Code steht doch kein Einziges.

    [EDIT]
    So, also verdammt nochmal...
    Ich möchte nen Vector haben, wo die Teile drin gespeichert sind und schön drin abhängen und nicht einfach Zeiger auf die lokalen Objekte haben, wie hier, weil wenn die Funktion vorbei ist, würden die teile im Vector nur auf Mist zeigen, das wäre dann also total Shit.
    Jetzt will ich also einfach so einen netten Vector haben...
    Außerdem soll der Vector sowohl die Klasse B als auch C speichern können, C ist ebenfalls von A abgeleitet.
    Deswegen dachte ich daran A zu nehmen, das müsste ja so eigentlich klappen.
    Geht das, oder nicht?
    Und wenn ja, wie bitte?
    *bettel*

    MfG MAV

    [ Dieser Beitrag wurde am 11.05.2003 um 17:04 Uhr von Mis2com editiert. ]



  • Also...

    Dieser Code funktioniert jetzt genauso wie ich will!

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    class A
    {
    public:
        bool classtype;
    public:
        ~A() {};
    };
    
    class B : public A
    {
    public:
        int a;
    };
    
    typedef vector<A*>           vecs;
    typedef vector<A*>::iterator vecs_it;
    
    vecs    vec;
    vecs_it vit;
    
    void write()
    {
        B* bla = new B;
        bla->a = 100;
        vec.push_back(bla);
        bla = 0;
        bla = new B;
        bla->a = 200;
        vec.push_back(bla);
    }
    
    void read()
    {
        for(vit = vec.begin(); vit != vec.end();)
        {
            B* temp = reinterpret_cast<B*>(*vit++);
            cout << temp->a;
        }
    }
    
    void del()
    {
        for(vit = vec.begin(); vit != vec.end();)
        {
            delete *vit++;
        }   
    }
    
    int main()
    {
        write();
        read();
        del();
    
        getchar();
    
        return 0;
    }
    

    Der Code funktioniert zu meiner völligen Zufriedenheit.
    Jetzt die Grettchen-Frage:
    Habt ihr ifrgendwelche Einwände oder Probleme mit dem Code???

    Es wird ein zeiger gemacht und Speicher allokiert.
    Die Adresse wird dann dem Vector gegeben.
    Da die Adresse nun gespeichert ist, kann der Zeiger auf 0 gesetzt werden und neuer Speicher an einer anderen Stelle allokiert werden.
    An der Stelle wird dann wieder der Wert verändert und die zweite Adresse auch gegeben.
    Am Ende wird dann alles durchlaufen und der Speicher wieder freigegeben.
    Argh, ist das so i.O.?

    MfG MAV

    [ Dieser Beitrag wurde am 11.05.2003 um 17:20 Uhr von Mis2com editiert. ]

    [ Dieser Beitrag wurde am 11.05.2003 um 17:28 Uhr von Mis2com editiert. ]



  • Danke, ich habe es jetzt hinbekommen, durch Hilfe von woanders (nicht, dass jemand denkt, ich schaff sowas ganz allein ;))
    Ich caste einfach garnet mehr, so einfach sieht's aus. ^^


Anmelden zum Antworten