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.pdf

    Da 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 CMatrix ein 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 auf CMatrix<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.


Anmelden zum Antworten