Template verständnis
-
Hallo !
Bin beim lesen eines Buches (C++ Codebook S.137) auf ein Problem gestoßen!
http://www.pearson.ch/download/media/9783827322852_SP.pdfDa steht:
CMatrix(size_type rows, size_type columns, const Type &obj=Type()) { resize(rows, columns, obj); }aber das Objekt m_elements ist doch noch nicht Inizialisiert. Wie kann man da schon auf resize zugreifen? Oder muss man das bei Templates nicht?
sollte doch so sein:
CMatrix(size_type rows, size_type columns, const Type &obj=Type()) : m_rows(rows), m_columns(columns){}Bin ich Dumm oder der Autor?

-
Bin ich Dumm oder der Autor?
Du bist nicht dumm, nur unwissend.
aber das Objekt m_elements ist doch noch nicht Inizialisiert. Wie kann man da schon auf resize zugreifen?
m_elements wurde default-initialisiert.
In dem meisten Fällen gilt: Wenn eine (nicht-statische) Membervariable nicht im Konstruktor in der Initialisierungsliste initialisiert wird, wird sie default-initialisiert. Das hat auch nichts mit Templates zu tun.
-
Sone schrieb:
In dem meisten Fällen gilt: Wenn eine (nicht-statische) Membervariable nicht im Konstruktor in der Initialisierungsliste initialisiert wird, wird sie default-initialisiert.
In welchem Fall gilt es nicht?
-
out schrieb:
Sone schrieb:
In dem meisten Fällen gilt: Wenn eine (nicht-statische) Membervariable nicht im Konstruktor in der Initialisierungsliste initialisiert wird, wird sie default-initialisiert.
In welchem Fall gilt es nicht?
In a non-delegating constructor, if a given non-static data member [...] is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
- if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5;
- otherwise, if the entity is a variant member (9.5), no initialization is performed;
- otherwise, the entity is default-initialized (8.5).
~Edit²: Nochmal Formatierung im Zitat korrigiert.~
Beispiel:
Seit C++11 ist folgendes möglich:struct Foo { int bar = 5; };
-
Hab das mal kurz getippt!
Mein Compiler will das nicht!
#include <cstdlib> #include <iostream> #include <vector> template<typename Type, typename Allocator = std::allocator < Type > > class CSaveVector : public std::vector<Type, Allocator> { public: typedef std::vector<Type, Allocator> base_type; typedef CSaveVector<Type, Allocator> my_type; typedef typename base_type::size_type size_type; typedef typename base_type::reference reference; typedef typename base_type::const_reference const_reference; //------------ constructoren ------------------ explicit CSaveVector(const Allocator &a = Allocator()) : base_type(a){} CSaveVector(const my_type &v) : base_type(v){} CSaveVector(size_type n, const Type &obj=Type(), const Allocator &a = Allocator()) : base_type(n,obj,a){} template<typename Input> CSaveVector(Input begin, Input end, const Allocator &a=Allocator()) : base_type(begin, end, a){} //----------- operatoren --------------- reference operator[](size_type offset){ return(at(offset)); } const_reference operator[](size_type offset) const{ return(at(offset)); } }; //===================================================================================== template<typename Type, typename Allocator > class CMatrix; //===================================================================================== template<typename Type, typename Allocator = std::allocator<Type> > class CMatrixVector : private CSaveVector<Type, Allocator>{ friend class CMatrix<Type, Allocator>; public: typedef CSaveVector<Type, Allocator> base_type; typedef CMatrixVector<Type, Allocator> my_type; typedef typename base_type::size_type size_type; typedef typename base_type::reference reference; typedef typename base_type::const_reference const_reference; explicit CMatrixVector(const Allocator &a=Allocator()) : base_type(a){} CMatrixVector(size_type n, const Type &obj=Type(), const Allocator &a=Allocator()) :base_type(n,obj,a){} reference operator[](size_type idx){ return (base_type::operator[](idx)); } const_reference operator[](size_type idx) const { return(base_type::operator[](idx)); } }; //======================================================================= template<typename Type, typename Allocator = std::allocator<Type> > class CMatrix : public std::vector<std::vector<Type> > { public: typedef CMatrix<Type, Allocator> my_type; typedef std::size_t size_type; typedef Type& reference; typedef const Type& const_reference; private: CMatrixVector<CMatrixVector<Type, Allocator>, Allocator > m_elements; size_type m_rows; size_type m_columns; public: CMatrix(size_type rows, size_type columns, const Type &obj=Type()) { resize(rows, columns, obj); } void resize(size_type rows, size_type columns, const Type &obj=Type()){ /* Größe des Zeilenvektors anpassen */ m_elements.resize(rows, CMatrixVector<Type, Allocator>(columns,obj)); /* Größe der Spaltenvektoren anpassen */ for(size_type r=0; r<rows; ++r) m_elements[r].resize(columns,obj); m_columns = columns; m_rows = rows; } }; int main (int argc, char* argv[]){ CMatrix<int> m(2,2); return EXIT_FAILURE; }
-
Steht das so im Buch
Sofort wegwerfen.Dieses
public std::vector<Type, Allocator>ist die Ursache aller Probleme.
Das unmittelbare Problem ist die nicht-öffentliche Vererbung in
class CMatrixVector : private CSaveVector<Type, Allocator>
-
Danke ellol !
Ja, stand so drin!
-
Ich habs mal genauer angeschaut.
Fehleranalyse:
template<typename Type, typename Allocator = std::allocator<Type> > class CMatrixVector : private CSaveVector<Type, Allocator>{ friend class CMatrix;Geht nicht, weil
CMatrixein Template ist. So stands im Buch.friend class CMatrix<Type, Allocator>;Ist zwar erlaubt, aber das bedeutet, dass für
CMatrixVector<CMatrixVector<Type, Allocator>, Allocator > m_elements;der Freund
CMatrix<CMatrixVector<Type, Allocator>, Allocator >heisst. Das passt aber nicht aufCMatrix<Type, Allocator>, was gebraucht wird.Lösung:
template<typename Type2, typename Allocator2> friend class CMatrix;Gibt aber noch einen weiteren Fehler:
reference operator[](size_type offset){ return(at(offset)); }muss
reference operator[](size_type offset){ return(this->at(offset)); }heissen.
Jetzt gehts.
...
Zum Inhalt.
Dein Buch missbraucht Vererbung. Hier sind einige Argumente, weshalb Vererbung in diesem Zusammenhang GAR KEINEN Sinn ergibt: http://stackoverflow.com/questions/6806173/subclass-inherit-standard-containers
Das Buch lehrt auch veralteten Stil. std::unary_function ist offiziell deprecated. Klassen mit "C" zu präfixen ist veralteter Stil der heute kaum noch anzutreffen ist.