Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 18
  1. #1

    [C++] Undefined symbols for architecture x86_64

    Ciao a tutti.
    Sto provando a scrivere un template di classi che rappresenterebbero dei vettori nel senso matematico del termine. Questa classe eredita direttamente da std::vector<T>.
    Tutto sembra andare per il meglio quando compilo con un main() vuoto, ma appena cerco di instanziare ed utilizzare la mia classe ottengo un errore strano:

    codice:
    Undefined symbols for architecture x86_64:
      "Vector<int>::Vector(unsigned long)", referenced from:
          _main in testVector.o
      "std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, Vector<int> const&)", referenced from:
          _main in testVector.o
    ld: symbol(s) not found for architecture x86_64
    collect2: ld returned 1 exit status
    make: *** [testVector] Error 1
    macbook-di-rocco-meli:Simulation roccomeli$ make clean
    rm -f *.o
    macbook-di-rocco-meli:Simulation roccomeli$ make
    g++gcc-4.6.x -std=c++0x   -c -o testVector.o testVector.cc
    g++gcc-4.6.x -std=c++0x   -c -o Vector.o Vector.cc
    g++gcc-4.6.x   testVector.o Vector.o   -o testVector
    Undefined symbols for architecture x86_64:
      "Vector<int>::Vector(unsigned long)", referenced from:
          _main in testVector.o
      "std::basic_ostream<char, std::char_traits<char> >& operator<< <int>(std::basic_ostream<char, std::char_traits<char> >&, Vector<int> const&)", referenced from:
          _main in testVector.o
    ld: symbol(s) not found for architecture x86_64
    collect2: ld returned 1 exit status
    make: *** [testVector] Error 1
    È come se il compilatore non trova l'implementazione della classe ma davvero non capisco come mai.

    Ecco il mio codice:
    codice:
    CC = g++gcc-4.6.x
    CXX = g++gcc-4.6.x
    CXXFLAGS = -std=c++0x
    
    all: testVector
    
    # --- TEST VECTOR ---
    testVector: testVector.o Vector.o
    testVector.o: testVector.cc Vector.h
    
    # --- CLASSES ---
    Vector.o: Vector.h Vector.cc
    
    clean:
    	rm -f *.o
    codice:
    #include "Vector.h"
    
    #include <iostream>
    using std::cout;
    using std::endl;
    
    #include <vector>
    using std::vector;
    
    #include <initializer_list>
    using std::initializer_list;
    
    int main()
    {
    	vector<double> V({0,1,2,3,4,5});
    	initializer_list<double> I({5,4,3,2,1,0});
    	
    	// --- TEST CONSTRUCTEURS ---
    	
    	Vector<int> v1(6);
    	cout << v1 << endl;
    	/*
    	Vector<int> v2(0.1,1.1,1.2);
    	cout << v2 << endl;
    	
    	Vector< > v3(V);
    	cout << v3 << endl;
    	
    	Vector< > v4(I);
    	cout << v4 << endl;
    	
    	Vector< > v5(v3);
    	cout << v5 << endl;
    	
    	// --- TEST OPERATEURS ---
    	cout << v2[0] << ' ' << v2[1] << ' ' << v3[2] << endl;
    	
    	v5 = v4;
    	cout << v5 << endl;
    	
    	if(v5 == v4){cout << v5 << " == " << v4 << endl;}
    	else{cout << v5 << " != " << v4 << endl;}
    	
    	if(v5 != v3){cout << v5 << " != " << v4 << endl;}
    	else{cout << v5 << " == " << v4 << endl;}
    	*/
    
    	return 0;
    }
    codice:
    #include "Vector.h"
    
    #include<stdexcept>
    #include<algorithm>
    #include<iterator>
    
    // *** PUBLIC ***
    // --- CONSTRUCTORS ---
    
    // Empty vector
    template<typename T>
    Vector<T>::Vector(size_t size)
    : std::vector<T>(size, 0)
    {}
    
    // 3D vector
    template<typename T>
    Vector<T>::Vector(T x, T y, T z)
    : std::vector<T>({x, y, z})
    {}
    
    template<typename T>
    Vector<T>::Vector(const std::vector<T> & V)
    : std::vector<T>(V)
    {}
    
    template<typename T>
    Vector<T>::Vector(const std::initializer_list<T>& V)
    : std::vector<T>(V)
    {}
    
    template<typename T>
    Vector<T>::Vector(const Vector<T>& V)
    {
    	if(*this != V)
    	{
    		*this = V;
    	}
    }
    
    // --- INNER OPERATORS ---
    template<typename T>
    bool Vector<T>::operator==(const Vector<T>& V) const
    {
    	bool b(true);
    
    	range_exception(V, "");
    
    	for(auto i : *this)
    	{
    		if(*this[i] != V[i])
    		{
    			b = false;
    			break;
    		}
    	}
    	
    	return b;
    }
    
    template<typename T>
    bool Vector<T>::operator!=(const Vector<T>& V) const
    {
    	range_exception(V, "");
    
    	return !(*this == V);
    }
    
    // --- EXTERNAL OPERATORS ---
    
    template<typename T>
    std::ostream& operator<<(std::ostream& out, const Vector<T>& V)
    {
    	std::copy(V.begin(), V.end(), std::ostream_iterator<T>(out, " "));
    	
    	return out;
    }
    
    // *** PRIVATE ***
    template<typename T>
    void Vector<T>::range_except(const Vector<T>& V, const std::string& s) const
    {
    	if(*this.size() != V.size())
    	{
    		throw std::range_error(s);
    	}
    }
    codice:
    #ifndef VECTOR_H
    #define VECTOR_H
    
    #include <vector>
    #include <initializer_list>
    #include <iostream>
    #include <string>
    
    template<typename T = double>
    class Vector : public std::vector<T>
    {
    public:
    	// --- CONSTRUCTORS ---
    	Vector(size_t);
    	Vector(T, T, T);
    	Vector(const std::vector<T> &);
    	Vector(const std::initializer_list<T>&);
    	Vector(const Vector<T>&);
    	
    	// --- INNER OPERATORS ---
    	bool operator==(const Vector<T>&) const;
        bool operator!=(const Vector<T>&) const;
    	
    private:
    	// --- METHODS ---
    	void range_except(const Vector<T>&, const std::string&) const;
    }; 
    
    // --- EXTERNAL OPERATORS
    template<typename T>
    std::ostream& operator<<(std::ostream&, const Vector<T>&);
    
    #endif
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  2. #2
    Utente bannato
    Registrato dal
    Apr 2012
    Messaggi
    510
    Prova ad aggiungere il flag -m32 .

  3. #3
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Il vero problema è che hai definito il tuo Vector in un file .cpp.
    Il codice del template deve stare in un .h, altrimenti il linker non trova i metodi istanziati dal compilatore.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  4. #4
    Originariamente inviato da shodan
    Il vero problema è che hai definito il tuo Vector in un file .cpp.
    Il codice del template deve stare in un .h, altrimenti il linker non trova i metodi istanziati dal compilatore.
    È proprio questo il problema. Grazie mille! Molto strano che non sia stato scritto sulle diapositive del corso...

    Ma allora che ne è della separazione interfaccia/implementazione?
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  5. #5
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    I template sono un'eccezione al paradigma, insieme alle funzioni dichiarate inline.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  6. #6
    Originariamente inviato da shodan
    I template sono un'eccezione al paradigma, insieme alle funzioni dichiarate inline.
    Ok. Grazie mille! =)

    Ho modificato come dici mettendo le definizioni nel file .h. Ottengo però gli errori seguenti, che non credo di capire... Ho già fatto questa classe senza templare ed era filato tutto liscio... =(

    codice:
    In file included from testVector.cc:1:0:
    Vector.h: In member function ‘bool Vector<T>::operator==(const Vector<T>&) const [with T = double]’:
    testVector.cc:41:11:   instantiated from here
    Vector.h:82:3: error: array subscript is not an integer
    Vector.h: In member function ‘void Vector<T>::range_except(const Vector<T>&, const string&) const [with T = double, std::string = std::basic_string<char>]’:
    Vector.h:78:2:   instantiated from ‘bool Vector<T>::operator==(const Vector<T>&) const [with T = double]’
    testVector.cc:41:11:   instantiated from here
    Vector.h:114:2: error: request for member ‘size’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    make: *** [testVector.o] Error 1
    Il codice é il seguente:

    codice:
    CC = g++gcc-4.6.x
    CXX = g++gcc-4.6.x
    CXXFLAGS = -std=c++0x
    
    all: testVector
    
    # --- TEST VECTOR ---
    testVector: testVector.o Vector.o
    testVector.o: testVector.cc Vector.h
    
    # --- CLASSES ---
    Vector.o: Vector.h
    
    clean:
    	rm -f *.o
    codice:
    #include "Vector.h"
    
    #include <iostream>
    using std::cout;
    using std::endl;
    
    #include <vector>
    using std::vector;
    
    #include <initializer_list>
    using std::initializer_list;
    
    int main()
    {
    	vector<double> V({0,1,2,3,4,5});
    	initializer_list<double> I({5,4,3,2,1,0});
    	
    	// --- TEST CONSTRUCTEURS ---
    	
    	Vector<int> v1(6);
    	cout << v1 << endl;
    	
    	Vector<double> v2(0.1,1.1,1.2);
    	cout << v2 << endl;
    	
    	Vector< > v3(V);
    	cout << v3 << endl;
    	
    	Vector< > v4(I);
    	cout << v4 << endl;
    	
    	Vector< > v5(v3);
    	cout << v5 << endl;
    	
    	// --- TEST OPERATEURS ---
    	cout << v2[0] << ' ' << v2[1] << ' ' << v3[2] << endl;
    	
    	v5 = v4;
    	cout << v5 << endl;
    	
    	if(v5 == v4){cout << v5 << " == " << v4 << endl;}
    	else{cout << v5 << " != " << v4 << endl;}
    	
    	if(v5 != v3){cout << v5 << " != " << v4 << endl;}
    	else{cout << v5 << " == " << v4 << endl;}
    
    	return 0;
    }
    codice:
    #ifndef VECTOR_H
    #define VECTOR_H
    
    #include <vector>
    #include <initializer_list>
    #include <iostream>
    #include <string>
    #include<stdexcept>
    #include<algorithm>
    #include<iterator>
    
    template<typename T = double>
    class Vector : public std::vector<T>
    {
    public:
    	// --- CONSTRUCTORS ---
    	Vector(size_t);
    	Vector(T, T, T);
    	Vector(const std::vector<T> &);
    	Vector(const std::initializer_list<T>&);
    	Vector(const Vector<T>&);
    	
    	// --- INNER OPERATORS ---
    	bool operator==(const Vector<T>&) const;
        bool operator!=(const Vector<T>&) const;
    	
    private:
    	// --- METHODS ---
    	void range_except(const Vector<T>&, const std::string&) const;
    }; 
    
    // --- EXTERNAL OPERATORS
    template<typename T>
    std::ostream& operator<<(std::ostream&, const Vector<T>&);
    
    #endif
    
    // *** PUBLIC ***
    // --- CONSTRUCTORS ---
    
    // Empty vector
    template<typename T>
    Vector<T>::Vector(size_t size)
    : std::vector<T>(size, 0)
    {}
    
    // 3D vector
    template<typename T>
    Vector<T>::Vector(T x, T y, T z)
    : std::vector<T>({x, y, z})
    {}
    
    template<typename T>
    Vector<T>::Vector(const std::vector<T> & V)
    : std::vector<T>(V)
    {}
    
    template<typename T>
    Vector<T>::Vector(const std::initializer_list<T>& V)
    : std::vector<T>(V)
    {}
    
    template<typename T>
    Vector<T>::Vector(const Vector<T>& V)
    {
    	if(*this != V)
    	{
    		*this = V;
    	}
    }
    
    // --- INNER OPERATORS ---
    template<typename T>
    bool Vector<T>::operator==(const Vector<T>& V) const
    {
    	bool b(true);
    
    	range_except(V, "");
    
    	for(auto i : *this)
    	{
    		if(*this[i] != V[i])
    		{
    			b = false;
    			break;
    		}
    	}
    	
    	return b;
    }
    
    template<typename T>
    bool Vector<T>::operator!=(const Vector<T>& V) const
    {
    	range_except(V, "");
    
    	return !(*this == V);
    }
    
    // --- EXTERNAL OPERATORS ---
    
    template<typename T>
    std::ostream& operator<<(std::ostream& out, const Vector<T>& V)
    {
    	std::copy(V.begin(), V.end(), std::ostream_iterator<T>(out, " "));
    	
    	return out;
    }
    
    // *** PRIVATE ***
    template<typename T>
    void Vector<T>::range_except(const Vector<T>& V, const std::string& s) const
    {
    	if(*this.size() != V.size())
    	{
    		throw std::range_error(s);
    	}
    }
    Ps: cosa ne pensate del codice? Lo utilizzereste o...? =)
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  7. #7
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Il problema dovrebbe essere qui. In questo modo recuperi il valore di *this, non l'indice. Per cui non puoi accedere a una locazione del vector tramite un double.
    In altre parole alla prima iterazione hai il valore di (*this)[0], alla seconda (*this[1]) etc.

    codice:
    for(auto i : *this)
    Se vuoi effettuare una comparazione degli elementi meglio usare std::equal
    http://en.cppreference.com/w/cpp/algorithm/equal
    avendo cura che i due range siano si uguale lunghezza, altrimenti va da se che sono diversi.

    Ps: cosa ne pensate del codice? Lo utilizzereste o...? =)
    o...
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  8. #8
    Originariamente inviato da shodan
    Il problema dovrebbe essere qui. In questo modo recuperi il valore di *this, non l'indice. Per cui non puoi accedere a una locazione del vector tramite un double.
    In altre parole alla prima iterazione hai il valore di (*this)[0], alla seconda (*this[1]) etc.

    codice:
    for(auto i : *this)
    Se vuoi effettuare una comparazione degli elementi meglio usare std::equal
    http://en.cppreference.com/w/cpp/algorithm/equal
    avendo cura che i due range siano si uguale lunghezza, altrimenti va da se che sono diversi.


    o... :ecco:
    Ho cambiato il codice dalla funzione in questo:
    codice:
    template<typename T>
    bool Vector<T>::operator==(const Vector<T>& V) const
    {
    	bool b(true);
    
    	if(*this.size() != V.size())
    	{
    		b = false;
    	}
    	else
    	{
    		b = equal(*this.begin(), *this.end(), V.begin());
    	}
    	
    	return b;
    }
    Ma mi da questo errore:
    codice:
    In file included from testVector.cc:1:0:
    Vector.h: In member function ‘bool Vector<T>::operator==(const Vector<T>&) const [with T = double]’:
    testVector.cc:41:11:   instantiated from here
    Vector.h:78:2: error: request for member ‘size’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    Vector.h:84:3: error: request for member ‘begin’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    Vector.h:84:3: error: request for member ‘end’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    Vector.h: In member function ‘void Vector<T>::range_except(const Vector<T>&, const string&) const [with T = double, std::string = std::basic_string<char>]’:
    Vector.h:93:2:   instantiated from ‘bool Vector<T>::operator!=(const Vector<T>&) const [with T = double]’
    testVector.cc:44:11:   instantiated from here
    Vector.h:112:2: error: request for member ‘size’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    make: *** [testVector.o] Error 1
    Sembra come se non ha ereditato correttamente i metodi di std::vector... In pratica é l'ereditarietà che mi da un po' di problemi a quanto pare (la prima volta che ho fatto la classe avevo semplicemente messo un std::vector come attributo privato)...

    Comunque perché non utilizzeresti il codice? Poco efficiente? Mal concepito? :spy:
    xD
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  9. #9
    Ho eseguito le seguenti modifiche e ora compila.

    Makefile:
    codice:
    CC = g++gcc-4.6.x
    CXX = g++gcc-4.6.x
    CXXFLAGS = -std=c++0x
    
    all: testVector
    
    # --- TEST VECTOR ---
    testVector: testVector.o
    testVector.o: testVector.cc Vector.h
    
    # --- CLASSES ---
    
    
    clean:
    	rm -f *.o
    Ho cambiato la vecchia istruzione che dava problemi in
    codice:
    this->size() != V.size()
    (Perché la precedente versione non funzionava?).

    Però ora ho il seguente problema, quando viene chiamato il costruttore di copia:
    codice:
    terminate called after throwing an instance of 'std::range_error'
      what():  
    Abort trap: 6
    K. L. Thompson
    You can't trust code that you did not totally create yourself.
    A. Bogk
    UNIX is user-friendly, it just chooses its friends.

  10. #10
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Io eviterei quando possibile di usare *this.begin() et similia . Meglio usare this->begin(), più elegante e non soggetto a eventuali precedenze di operatori. E l'errore:
    Vector.h:78:2: error: request for member ‘size’ in ‘this’, which is of non-class type ‘const Vector<double>* const’
    sembra indicare che prima venga richiesto il metodo size() e solo dopo venga dereferenziato this.
    In caso di dubbio usa sempre (*this).qualcosa() e vai sul sicuro (fermo restando che this->qualcosa() rimane migliore per leggibilità.

    Gli iteratori poi dovrebbero essere costanti, quindi usa cbegin(), cend() all'interno di metodi const. Terza cosa quel bool dovrebbe essere mutable bool dato che lo modifichi all'interno di un metodo const. Tuttavia il metodo mi pare macchinoso.
    codice:
    template<typename T>
    bool Vector<T>::operator==(const Vector<T>& V) const
    {
        if (this->size() == V.size()) {
            return equal(this->cbegin(),this->cend(),V.cbegin());
        }
        return false;
    }
    mi pare più lineare.

    Comunque perché non utilizzeresti il codice? Poco efficiente? Mal concepito?
    Le classi STL non hanno distruttore virtuale pertanto non si dovrebbe corretto ereditare da esse, ma se non allochi dati in Vector non hai problemi immediati.
    Il fatto è che non capisco la scelta implementativa. Voglio dire: qui
    codice:
    // 3D vector
    template<typename T>
    Vector<T>::Vector(T x, T y, T z)
    : std::vector<T>({x, y, z})
    {}
    acquisisci tre valori che intuisco essere tre coordinate. Ma un vector<> contiene un solo punto per locazione. Questo comporta un po' di acrobazie per ricavare, calcolare e salvare i dati. Io avrei optato per un vector di struct point3D (una tupla di 3 elementi in C++11), eventualmente incapsulando tale vector in una classe che mi semplichi eventuali calcoli e facendo un forward degli iteratori per usare la classe contenitrice con gli algoritmi standard.
    Comunque al momento non mi serve una classe Vector Matematico per questo non "grabbo" il codice
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.