vector clear und const variable



  • Moin,

    ich muss ein Java Programm in C++ umwandeln, dabei entstehen zwei Probleme die, wie ich vermute eine ähnliche Ursache haben.

    Aber ich fange lieber erstmal mit dem ersten Problem an, da mir das zweite etwas kompliziert erscheint.

    Ich habe zwei Klassen:

    class clEins
    {
        public:
            const int E;
            clEins():E(2)
            {
               //nichts
            };
    
    };
    
    class clZwei
    {
        private:
            vector<clEins> a;
    
        public:
            void test()
            {
                this->a.clear();
            };
    };
    

    Beim Compilieren tritt folgender Fehler auf:

    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h: In member function `clEins& clEins::operator=(const clEins&)':
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:247:   instantiated from `_OutputIterator std::__copy(_RandomAccessIterator, _RandomAccessIterator, _OutputIterator, std::random_access_iterator_tag) [with _RandomAccessIterator = clEins*, _OutputIterator = clEins*]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:266:   instantiated from `_OutputIterator std::__copy_aux2(_InputIterator, _InputIterator, _OutputIterator, __false_type) [with _InputIterator = clEins*, _OutputIterator = clEins*]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:296:   instantiated from `_OutputIterator std::__copy_ni2(_InputIterator, _InputIterator, _OutputIterator, __true_type) [with _InputIterator = clEins*, _OutputIterator = __gnu_cxx::__normal_iterator<clEins*, std::vector<clEins, std::allocator<clEins> > >]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:317:   instantiated from `_OutputIterator std::__copy_ni1(_InputIterator, _InputIterator, _OutputIterator, __true_type) [with _InputIterator = __gnu_cxx::__normal_iterator<clEins*, std::vector<clEins, std::allocator<clEins> > >, _OutputIterator = __gnu_cxx::__normal_iterator<clEins*, std::vector<clEins, std::allocator<clEins> > >]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:358:   instantiated from `_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<clEins*, std::vector<clEins, std::allocator<clEins> > >, _OutputIterator = __gnu_cxx::__normal_iterator<clEins*, std::vector<clEins, std::allocator<clEins> > >]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/vector.tcc:121:   instantiated from `typename std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(__gnu_cxx::__normal_iterator<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >, __gnu_cxx::__normal_iterator<typename _Alloc::pointer, std::vector<_Tp, _Alloc> >) [with _Tp = clEins, _Alloc = std::allocator<clEins>]'
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_vector.h:701:   instantiated from `void std::vector<_Tp, _Alloc>::clear() [with _Tp = clEins, _Alloc = std::allocator<clEins>]'
    newmain.cc:23:   instantiated from here
    /usr/lib/gcc/i686-pc-mingw32/3.4.4/include/c++/bits/stl_algobase.h:247: error: non-static const member `const int clEins::E', can't use default assignment operator
    

    Irgendwie mag er da was mit der konstanten nicht. Denn wenn ich in dem Programm die Konstante E auskommentiere tritt der Fehler nicht mehr auf.

    Kann mir jemand weiter helfen?



  • Für eine selbstdefinierte Klasse erzeugt dir der Compiler normalerweise ein paar Default-Methoden (Copy-Ctor, operator=, Dtor, in den meisten Fällen auch einen Default-Ctor), die die jeweiligen Methoden der Basisklasse(n) und Membervariablen verwenden. Wenn eine der verwendeten Methoden nicht verfügbar ist, kommt der angegebene Fehler.

    In deinem Fall: Eine Konstante kann nicht zugewiesen werden, deshalb kann der Compiler auch keinen Default-operator= für deine Klasse bereitstellen (weil sie eine Konstante enthält). Zur Lösung kannst du entweder das 'const' weglassen oder du stellst einen eigenen operator= bereit.



  • Du hast keinen Copy Konstruktor bzw. Copy-Operator definiert. Dadurch versucht der default nun alle Elemente zu kopieren. Das ist aber nich möglich, denn Du hast E als konstant definiert. Wenn der Copy-Operator/Konstruktor E auslassen würde, dann würde das auch gehen. Die Frage ist ob Du das möchtest?

    Wenn es Deine Intention ist E zu schützen wäre ein Getter/Setter Paar hier besser angebracht.



  • Noch eine Möglichkeit: Da E ja aller Wahrscheinlichkeit nach (:D) in jeder Instanz und für alle Zeiten den selben Wert haben dürfte (solange Du nicht mit const_casts hantierst), böte sich hier evtl. ein static const Member an.



  • hmmmm

    also die Konstante soll schon konstant bleiben. Ich möchte nicht das jemand die const int E verändern kann. Wenn ich euch richtig verstanden habe, dann muss ich den Default-operator= neu definieren. Da ich sowas noch nie gemacht habe würde ich gerne wissen wie das dann aussehen muss?

    e: aaaaaah mit static const int E geht es, das wäre natürlich auch eine Möglichkeit.



  • Das Problem mit dem "eine Konstante soll konstant bleiben" ist die Tatsache, daß diese Bedingung auch gnadenlos durchgezogen wird. Und was soll deiner Meinung nach herauskommen, wenn du `clEins ob1,ob2;...ob2=ob1;

    setzt? Dasob2.E` konstant ist, würde das Objekt nach der Zuweisung einen Teil seines alten Status beibehalten, also möglicherweise nicht identisch zu ob1 sein.

    Wenn wirklich alle Objekte von deinem Typ den selben Konstanten-Wert verwenden wollen, ist es am besten, du definierst E als statische Konstante (dann gehört sie dem gesamten Typ:

    class clEins
    {
    public:
      static const int E;
    };
    
    const int clEins::E = 2;//Definition und Initialisierung in der CPP
    


  • Okay also erstmal DANKE. Ich werde das ganze erstmal mit static const umsetzen und meinem Chef zeigen und wenn es ihm so nicht passt oder es nicht die Aufgabe erfüllt werde ich mich bestimmt noch mal melden.



  • Entweder static const oder eben garnicht const. Was von beiden "richtig" ist kommt darauf on ob E wirklich immer den gleichen Wert hat, oder manchmal mit 2 aber auch manchmal mit was anderem initialisiert wird.

    Auch stellt sich mir die Frage ob es bei einer Konvertierung Java -> C++ nicht besser wäre die Reference-Semantik beizubehalten, und einfach (smart) Pointer in den vector reinzustecken. Dann müssen die Objekte nicht zuweisbar sein, dann kann auch das const bleiben.


Anmelden zum Antworten