ERRO: undefined reference to - C++

9 respostas
H

Estou tentando fazer uma lista de funcionários. Na teoria, tudo parece correto, exceto pelo fato de aparecer o erro: undefined reference to

Alguém consegue achar o erro aqui?

Vou postar o código e o erro no final.

/* 
 * File:   Funcionario.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:14
 */

#ifndef FUNCIONARIO_H
#define	FUNCIONARIO_H

#include <string>

using namespace std;

typedef class Funcionario {
private:
    string nome;
    long cpf;
    string endereco;
    string cidade;
    string estado;
public:

    string GetCidade() {
        return cidade;
    }

    void SetCidade(string cidade) {
        this->cidade = cidade;
    }

    long GetCpf() {
        return cpf;
    }

    void SetCpf(long cpf) {
        this->cpf = cpf;
    }

    string GetEndereco() {
        return endereco;
    }

    void SetEndereco(string endereco) {
        this->endereco = endereco;
    }

    string GetNome() {
        return nome;
    }

    void SetNome(string nome) {
        this->nome = nome;
    }

    string GetEstado() {
        return estado;
    }

    void SetEstado(string uf) {
        this->estado = uf;
    }
} Funcionario;

#endif	/* FUNCIONARIO_H */
/* 
 * File:   ListaSimples.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:49
 */

#ifndef LISTASIMPLES_H
#define	LISTASIMPLES_H

template <class T>
class No {
private:
    T info;
    No<T> *prox;
public:
    No(T info, No<T> *prox);
    
    T GetInfo() {
        return info;
    }

    void SetInfo(T info) {
        this->info = info;
    }

    No<T>* GetProx() {
        return prox;
    }

    void SetProx(No<T>* prox) {
        this->prox = prox;
    }

};

template <class T>
No<T>::No(T info, No<T> *prox) {
    this->SetInfo(info);
    this->SetProx(prox);
}

#endif	/* LISTASIMPLES_H */
/* 
 * File:   Lista.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 21:25
 */

#ifndef LISTA_H
#define	LISTA_H

#include <iostream>

#include "No.h"

template <class tipo>
class Lista{
    private:
        No <tipo> *inicio;
    public:
        Lista();
        ~Lista();
        void insert(tipo elem);
        int remove(tipo elem);
        int empty();
        
        No<tipo>* getInicio() const {
            return inicio;
        }

        void setInicio(No<tipo>* inicio) {
            this->inicio = inicio;
        }

};

template <class tipo>
Lista<tipo>::Lista() {this->setInicio(NULL);}

template <class tipo>
int Lista <tipo> :: empty(){
    if(!inicio)
        return 1;
    else
        return 0;
};

template <class tipo>
void Lista <tipo> :: insert(tipo elem){
    No <tipo> *ant=NULL, *atual,*novo;
    novo = new No <tipo>(elem, NULL);

    if(empty())
        inicio=novo;
    else{
        atual=inicio;
        while(atual!=NULL && atual->GetInfo() <= elem){
            ant=atual;
            atual=atual->GetProx();
        }
        if(ant==NULL){//inicio
            novo->GetProx() = inicio;
            inicio=novo;
        }
        else{//meio ou fim
            ant->GetProx() = novo;
            novo->GetProx() = atual;
        }
    }
}

template <class tipo>
int Lista <tipo> :: remove(tipo elem){
    No <tipo> *ant=NULL,*atual;

    if(empty())
        return -1;
    else{
        atual = inicio;

        while( atual && (atual->GetInfo() < elem)){
            ant=atual;
            atual=atual->GetProx();
        }

        if(atual!=NULL && atual->GetInfo() == elem){
            if(ant==NULL)//inicio
                inicio=atual->GetProx();
            else//meio ou fim
                ant->GetProx()=atual->GetProx();
            delete atual;
            return 0;
        }
        else
            return 1; //nao existe
    }
}

template <class tipo>
Lista <tipo> :: ~Lista(){
    No <tipo> *p;

    while(inicio!=NULL){
        p=inicio;
        inicio=inicio->GetProx();
        delete p;
    }
}

#endif	/* LISTA_H */
/* 
 * File:   main.cpp
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:31
 */

#include <cstdlib>
#include <iostream>
#include <string>

#include "Funcionario.h"
#include "Lista.h"

/*
 * 
 */
int main(int argc, char** argv) {
    Funcionario f;
    f.SetNome("Higor");
    f.SetCpf[telefone removido]); 
    f.SetEndereco("Rua Ipiranga, 1283"); 
    f.SetCidade("Dourados"); 
    f.SetEstado("MS");
    Lista<Funcionario> lista;
    
    lista.insert(f);
    
    //cout << lista.getInicio()->GetInfo().GetCpf();
//    lista.~Lista();
    return 0;
}
build/Debug/GNU-Linux-x86/main.o: In function `main':
/home/higornucci/NetBeansProjects/CppApplication_2/main.cpp:25: undefined reference to `Lista<Funcionario>::Lista()'
/home/higornucci/NetBeansProjects/CppApplication_2/main.cpp:27: undefined reference to `Lista<Funcionario>::insert(Funcionario)'
collect2: ld returned 1 exit status

9 Respostas

V
  1. Remova o typedef da classe Funcionario. Além de confuso ele é inútil.

  2. A classe funcionário não deveria ser inline (implementada inteira no .h). Templates sim, devem ser inline. No caso do seu exercício é mais claro se você optar em cada classe por fazer inline totalmente ou não fazer totalmente. Não misture as coisas como fez na Lista.h.

  3. Todos os seus métodos “getters” deveriam ser const;

  4. C++ != Java. Procure as boas práticas da linguagem. Seu código não segue praticamente nenhuma.

V

Na linha 56 do lista.h você faz:
while(atual!=NULL && atual->GetInfo() <= elem){

Note que isso implica que seu tipo é comparável com <=. No caso, o Tipo funcionário não é.
Revise essa comparação. Ela se repete também na linha 80.

Talvez falte simplesmente implementar o operador de <= para sua classe funcionário.

V

Ok. Gastei um tempinho e fiz a correção das classes. Não testei se a classe lista funciona, apenas fiz algumas correções e apliquei algumas práticas melhores. Em termos de C++, o código ainda está bem longe de ser considerado bom.
Coloquei vários comentários no código, explicando as mudanças.

/* 
 * File:   Funcionario.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:14
 */

#ifndef __FUNCIONARIO_H__
#define	__FUNCIONARIO_H__

#include &lt;string&gt;

using namespace std;

class Funcionario 
{
	private:
		string nome;
		string cpf;
		string endereco;
		string cidade;
		string estado;
	public:
		string GetCidade() 
		{
			return cidade;
		}

		//Evite cópias nas passagens de parâmetro
		//Dê garantia const se não for alterar o parâmetro de entrada
		void SetCidade(const string& cidade) 
		{
			this-&gt;cidade = cidade;
		}

		//Declare métodos que não mudam a classe como const
		//Evite a cópia também dos valores de retorno, se possível
		const string& GetCpf() const 
		{
			return cpf;
		}

		void SetCpf(const string& cpf) 
		{
			this-&gt;cpf = cpf;
		}

		const string& GetEndereco() const 
		{
			return endereco;
		}

		void SetEndereco(const string& endereco) 
		{
			this-&gt;endereco = endereco;
		}

		const string& GetNome() const 
		{
			return nome;
		}

		void SetNome(const string& nome) 
		{
			this-&gt;nome = nome;
		}

		const string& GetEstado() const 
		{
			return estado;
		}

		void SetEstado(const string& uf) 
		{
			this-&gt;estado = uf;
		}

		bool operator &lt; (const Funcionario& funcionario) const
		{
			return nome &lt; funcionario.nome;
		}

		bool operator &lt;= (const Funcionario& funcionario) const
		{
			return nome &lt; funcionario.nome;
		}

		bool operator == (const Funcionario& funcionario) const
		{
			return nome &lt; funcionario.nome;
		}
};

#endif	/* __FUNCIONARIO_H__ */
/* 
 * File:   Lista.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 21:25
 */

#ifndef LISTA_H
#define	LISTA_H

#include &lt;iostream&gt;

#include "No.h"

template &lt;class tipo&gt;
class Lista
{
    private:
        No &lt;tipo&gt; *inicio;
    public:
		//Use a lista de inicialização nos construtores
        Lista() : inicio(NULL)
		{
		}

        ~Lista()
		{
			No &lt;tipo&gt; *p;

			while(inicio!=NULL){
				p=inicio;
				inicio=inicio-&gt;GetProx();
				delete p;
			}			
		}

        void insert(const tipo& elem)
		{
			No &lt;tipo&gt; *ant=NULL, *atual,*novo;
			novo = new No &lt;tipo&gt;(elem, NULL);

			if(empty())
				inicio=novo;
			else
			{
				atual=inicio;
				while(atual!=NULL && atual-&gt;GetInfo() &lt;= elem)
				{
					ant=atual;
					atual=atual-&gt;GetProx();
				}

				if(ant==NULL) //inicio
				{
					novo-&gt;SetProx(inicio);
					inicio=novo;
				}
				else //meio ou fim
				{
					//Você não criou os setters à toa.
					ant-&gt;SetProx(novo);
					novo-&gt;SetProx(atual);
				}
			}
		}

		//Use booleans para representar o retorno booleano.
		// um sentido forte para o retorno. true é se removeu, false se não removeu.
        bool remove(const tipo& elem)
		{
			No &lt;tipo&gt; *ant=NULL,*atual;

			//Se tem return, não precisa de else.
			if(empty())
				return false; 
			
			atual = inicio;

			while( atual && (atual-&gt;GetInfo() &lt; elem))
			{
				ant=atual;
				atual=atual-&gt;GetProx();
			}

			if(atual!=NULL && atual-&gt;GetInfo() == elem)
			{
				if(ant==NULL)//inicio
					inicio=atual-&gt;GetProx();
				else//meio ou fim
					ant-&gt;GetProx()=atual-&gt;GetProx();
				delete atual;
				return true;
			}

			return false; //nao existe
		}
				
        bool empty() const  
		{
			//Evite ifs desnecessários
			return !inicio;
		}
		
        No&lt;tipo&gt;* getInicio() const 
		{
            return inicio;
        }
};

#endif	/* LISTA_H */
/* 
 * File:   No.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:49
 */

#ifndef __NO_H__
#define	__NO_H__

template &lt;class T&gt;
class No {
private:
    T info;
    No&lt;T&gt; *prox;
public:
    No(const T& _info, No&lt;T&gt;* _prox)
		: info(_info), prox(_prox)
	{
	}
    
    const T& GetInfo() const
	{
        return info;
    }

    T& GetInfo()
	{
        return info;
    }

    No&lt;T&gt;* GetProx() const
	{
        return prox;
    }

    void SetProx(No&lt;T&gt;* prox) 
	{
        this-&gt;prox = prox;
    }
};



#endif	/* __NO_H__ */
/* 
 * File:   main.cpp
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:31
 */

#include &lt;cstdlib&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;

#include "Funcionario.h"
#include "Lista.h"

int main(int argc, char** argv) 
{
    Funcionario f;
    f.SetNome("Higor");
    f.SetCpf("[telefone removido]");
    f.SetEndereco("Rua Ipiranga, 1283"); 
    f.SetCidade("Dourados"); 
    f.SetEstado("MS");
    Lista&lt;Funcionario&gt; lista;
    
    lista.insert(f);
    
    cout &lt;&lt; lista.getInicio()-&gt;GetInfo().GetCpf();
    return 0;
}
H

Olá, ViniGodoy!

Agradeço muito pelas respostas. Meu código estava uma "caca" mesmo.

Fiz alguns ajustes, de acordo com suas instruções, e consegui um código mais conciso. Em relação as boas práticas eu achei pouca coisa que realmente possa me ajudar. Talvez eu tenha usado as palavras chaves erradas, mas vou continuar procurando.

Fiquei com dúvida no que acontece aqui.

Lista() : inicio(NULL)  
        {  
        }
e aqui:
No(const T& _info, No<T>* _prox)  
        : info(_info), prox(_prox)  
    {  
    }

Vou postar minhas alterações:

Optei por fazer tudo inline e realmente o código esta mais compreensível. Coloquei o que é privado como privado mesmo evitando, dessa forma, o acesso indevido a atributos da minha classe. Assim, o encapsulamento realmente acontece. O que não existia antes.
/* 
 * File:   No.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:49
 */

#ifndef __NO_H__
#define	__NO_H__

template <class tipo>
class No {
private:
    No<tipo> *prox;
    tipo info;
public:    
    No(tipo info, No<tipo> *prox) 
    {
        this->info = info;
        this->prox = prox;
    }
    
    const tipo& GetInfo() const  
    {  
        return info;  
    }  
  
    tipo& GetInfo()  
    {  
        return info;  
    }  
  
    No<tipo>* GetProx() const  
    {  
        return prox;  
    }  
  
    void SetProx(No<tipo>* prox)   
    {  
        this->prox = prox;  
    }  
};

#endif	/* __NO_H__ */
Aqui na classe lista eu adicionei mais alguns métodos: busca : para saber se o elemento já existe ou não em minha lista. Pois, vou usar um atributo id na minha classe Funcionário para distinguir uma da outra. adiciona : agora retorna verdadeiro ou falso. Falso se o elemento já tiver um id igual na lista. No caso de verdadeiro ele incrementa o atributo tamanho da lista. tamanho : para saber quantos elementos a lista contém. get : para pegar um elemento em determinada posição.
/* 
 * File:   Lista.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 21:25
 */

#ifndef LISTA_H
#define	LISTA_H

#include <iostream>

#include "No.h"

template <class tipo>
class Lista{
private:
    No <tipo> *inicio;
    int tam;
public:
    Lista() 
    {
        this->inicio = NULL ;
    }
    
    ~Lista()
    {
        No <tipo> *p;

        while(inicio!=NULL){
            p=inicio;
            inicio = inicio->GetProx();
            delete p;
        }
    }

    bool empty()
    {
        return !inicio;
    };

    bool adiciona(const tipo& elem)  
    {  
        No <tipo> *ant=NULL, *atual,*novo;  
        novo = new No <tipo>(elem, NULL);  
        if(busca(elem))
            return false;
        if(empty())  
            inicio=novo;  
        else  
        {  
            atual=inicio;  
            while(atual!=NULL && atual->GetInfo() <= elem)  
            {  
                ant=atual;  
                atual=atual->GetProx();  
            }  

            if(ant==NULL) //inicio  
            {  
                novo->SetProx(inicio);  
                inicio=novo;  
            }  
            else //meio ou fim  
            {  
                ant->SetProx(novo);  
                novo->SetProx(atual);  
            }  
        }  
        this->tam++;
        return true;
    }  

    bool remove(const tipo& elem)  
    {  
        No <tipo> *ant=NULL,*atual;  
        
        if(empty())  
            return false;   

        atual = inicio;  

        while( atual && (atual->GetInfo() < elem))  
        {  
            ant=atual;  
            atual=atual->GetProx();  
        }  

        if(atual!=NULL && atual->GetInfo() == elem)  
        {  
            if(ant==NULL)//inicio  
                inicio=atual->GetProx();  
            else//meio ou fim  
                ant->GetProx()=atual->GetProx();  
            delete atual;
            this->tam--;
            return true;  
        }  

        return false; //nao existe  
    }  

    bool busca(const tipo& elem) 
    {
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           if(aux->GetInfo() == elem)
               return true;
        return false;
    }

    tipo get(const int& pos) const
    {
        int posAux = 1;
        tipo auxT;
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           if(posAux == pos)
               return auxT = aux->GetProx();
           posAux++;
        return auxT = NULL;
    }

    const int& tamanho() const
    {
        int posAux = 0;
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           posAux++;
        return posAux;
    }

    No<tipo>* GetInicio() const 
    {
        return inicio;
    }

};

#endif	/* LISTA_H */
No caso da classe Funcionario as alterações ficaram em 3 operadores sobrecarregados para poder comparar duas classes através de seu id e uma função membro para imprimir os dados da classe.
/* 
 * File:   Funcionario.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:14
 */

#ifndef FUNCIONARIO_H
#define	FUNCIONARIO_H

#include <string>

using namespace std;

class Funcionario {
private:
    int id;
    string nome;
    long cpf;
    string endereco;
    string cidade;
    string estado;
public:
    void imprimir() 
    {
        cout << "Id: " << this->GetId() << endl;
        cout << "Nome: " << this->GetNome() << endl;
        cout << "Cpf: " << this->GetCpf() << endl;
        cout << "Endereco: " << this->GetEndereco() << endl;
        cout << "Cidade: " << this->GetCidade() 
             << " Estado: " << this->GetEstado() 
             << endl
             << " --------------------------------------------- "
             << endl;
    }

    const string& GetCidade() const 
    {
        return cidade;
    }

    void SetCidade(const string& cidade) 
    {
        this->cidade = cidade;
    }

    const long& GetCpf() const 
    {
        return cpf;
    }

    void SetCpf(const long& cpf) 
    {
        this->cpf = cpf;
    }

    const string& GetEndereco() const 
    {
        return endereco;
    }

    void SetEndereco(const string& endereco) 
    {
        this->endereco = endereco;
    }

    const string& GetEstado() const 
    {
        return estado;
    }

    void SetEstado(const string& estado) 
    {
        this->estado = estado;
    }

    const int& GetId() const 
    {
        return id;
    }

    void SetId(const int& id) 
    {
        this->id = id;
    }

    const string& GetNome() const 
    {
        return nome;
    }

    void SetNome(const string& nome) 
    {
        this->nome = nome;
    }
    
    bool operator ==(const Funcionario& funcionario) const 
    {
        if(this->GetId() != funcionario.GetId()) return false;
        return true;
    }
    
    bool operator !=(const Funcionario& funcionario) const 
    {
        if(this->GetId() == funcionario.GetId()) return false;
        return true;
    }
    
    bool operator <=(const Funcionario& funcionario) const 
    {
        if(this->GetId() <= funcionario.GetId()) return true;
        return false;
    }
    
};

#endif	/* FUNCIONARIO_H */
/* 
 * File:   main.cpp
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:31
 */

#include <cstdlib>
#include <iostream>
#include <string>

#include "Lista.h"
#include "Funcionario.h"

/*
 * 
 */
int main(int argc, char** argv) {
    Funcionario f;
    f.SetId(1);
    f.SetNome("Higor");
    f.SetCpf[telefone removido]); 
    f.SetEndereco("Rua Ipiranga, 1283"); 
    f.SetCidade("Dourados"); 
    f.SetEstado("MS");
    
    Funcionario f2;
    f2.SetId(2);
    f2.SetNome("Henrique");
    f2.SetCpf[telefone removido]); 
    f2.SetEndereco("Rua Ipiranga, 1283"); 
    f2.SetCidade("Dourados"); 
    f2.SetEstado("MS");
    
    Lista<Funcionario> listaFunc;
    
    listaFunc.adiciona(f);
    listaFunc.adiciona(f2);
    
    if(listaFunc.empty() == 1) {
        cout << "vazia";
    }
    
    
    for(No<Funcionario>* p = listaFunc.GetInicio();
            p != NULL; p = p->GetProx()) {
        p->GetInfo().imprimir();
    }
    
    listaFunc.~Lista();
    return 0;
}

Gostaria da sua opinião em alguns pontos.
Você acha que sobrecarregar os operadores e verificar se o funcionário já existe através de seu id fica correto (da para manter ordenado)?

Adicionei uma nova classe chama Usuario que adiciona um usuário para algum funcionário. Esta correto fazer ... ?
/* 
 * File:   Usuario.h
 * Author: higornucci
 *
 * Created on 27 de Agosto de 2011, 14:41
 */

#ifndef USUARIO_H
#define	USUARIO_H

#include <string>
#include <iostream>
#include "Funcionario.h"

using namespace std;

class Usuario {
private:
    int id;
    string login;
    string senha;
    Funcionario funcionario;
public:
    void imprimir() 
    {
        cout << "Login: " << this->GetLogin() const << endl;
        cout << "Senha: " << this->GetSenha() const << endl;
    }
    
    const Funcionario& GetFuncionario() const 
    {
        return funcionario;
    }

    void SetFuncionario(const Funcionario& funcionario) 
    {
        this->funcionario = funcionario;
    }

    const int& GetId() const 
    {
        return id;
    }

    void SetId(const int& id) 
    {
        this->id = id;
    }

    const string& GetLogin() const 
    {
        return login;
    }

    void SetLogin(const string& login) 
    {
        this->login = login;
    }

    const string& GetSenha() const 
    {
        return senha;
    }

    void SetSenha(const string& senha) 
    {
        this->senha = senha;
    }
    
    bool operator ==(const Usuario& _user) const 
    {
        if(this->GetId() != _user.GetId()) return false;
        return true;
    }
    
    bool operator !=(const Usuario& _user) const 
    {
        if(this->GetId() == _user.GetId()) return false;
        return true;
    }
    
    bool operator <=(const Usuario& _user) const 
    {
        if(this->GetId() <= _user.GetId()) return true;
        return false;
    }

};

#endif	/* USUARIO_H */
V

higornucci:
Fiquei com dúvida no que acontece aqui.

No(const T& _info, No<T>* _prox)  
        : info(_info), prox(_prox)  
{  
}

Essa é a lista de inicialização. Ela é mais ou menos equivalente a isso aqui:

No(const T& _info, No<T>* _prox)  
{  
    info = _info;
    prox = _prox;
}

Mas há uma diferença: No segundo caso (dentro das chaves), o C++ fará primeiro a inicialização dos atributos info e prox usando o construtor padrão, e só depois rodará o código dentro das chaves, sobrescrevendo os valores inicializados pelos passados por parâmetro. Note então que acaba havendo 2 inicializações. No caso de um ponteiros e variáveis primitivas, isso não é um grande problema. Mas no caso do Tipo T da sua lista, sim, pois:
a) O C++ irá exigir que o tipo T tenha um construtor vazio, que será chamado no momento da inicialização;
b) Esse valor será depois excluído, e substituído por uma cópia gerada na atribuição dentro das chaves.

Note que o caso a) é duplamente indesejável: Nem queremos uma inicialização que não serve para nada, nem queremos obrigar a quem usa a lista ter um construtor vazio.

A lista de inicialização é que comanda qual inicialização de atributos será feita. Se ela estiver em branco, o construtor padrão é chamado().
Caso contrário, o atributo é inicializado por ela. Por isso, da forma do primeiro código, com a lista, essa dupla inicialização não ocorre.
Simplesmente o construtor de cópia será chamado, inicializando o T interno.

Sim. É a forma também que as classes padrão do C++, da STL, trabalham. Classes como std::set:
http://www.cplusplus.com/reference/stl/set/

A única diferença é que no std::set o comando de comparação é um functor, um outro template, que simula uma função. E por padrão a comparação é feita através do functor less que usa o operador de menor <. Essa sofisticação dá a flexibilidade do programador da lista escolher como quer ordenar seus elementos internos. Como você está estudando C++ agora, não recomendo que use algo tão sofisticado por enquanto.

Uma dica: Apenas com a implementação do operador de < e do operador de ==, você pode obter o sinal de maior, já que ele é o oposto do <=:

bool maiorQue(T x, T y) {
   return !(x < y && x == y);
}

Se usar esse truque, retira a exigência de quem usa sua lista de implementar o operador de >.

V

Se quiser se aprofundar em C++, dê uma olhada nesse roadmap:
http://pontov.com.br/site/cpp/46-conceitos-basicos/88-roadmap-c

Recomendo muito o livro Effective C++, que explica boas práticas e pegadinhas da linguagem (como essa da lista de inicialização, ou o detalhe de usar const& para passar parâmetros).

É muito útil para entender o paradigma de programação do C++, e não tanto programar C++ como se fosse Java, ou como se fosse C.

H

Agora começou a dar o seguinte erro no método remove da classes Lista.h:

Lista.h: In member function `bool Lista<tipo>::remove(const tipo&) [with tipo = Funcionario]':
main.cpp:37:   instantiated from here
Lista.h:94: error: non-lvalue in assignment
make[2]: *** [build/Debug/Cygwin-Windows/main.o] Error 1
make[1]: *** [.build-conf] Error 2
make: *** [.build-impl] Error 2

A classe Lista.h:

/* 
 * File:   Lista.h
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 21:25
 */

#ifndef LISTA_H
#define	LISTA_H

#include <iostream>
using namespace std;
#include "No.h"

template <class tipo>
class Lista{
private:
    No <tipo> *inicio;
    int tam;
public:
    Lista() 
    {
        this->inicio = NULL ;
    }
    
    ~Lista()
    {
        No <tipo> *p;

        while(inicio!=NULL){
            p=inicio;
            inicio = inicio->GetProx();
            delete p;
        }
    }

    bool empty()
    {
        return !inicio;
    };

    bool adiciona(const tipo& elem)  
    {  
        No <tipo> *ant=NULL, *atual,*novo;  
        novo = new No <tipo>(elem, NULL);  
        if(busca(elem))
            return false;
        if(empty())  
            inicio=novo;  
        else  
        {  
            atual=inicio;  
            while(atual!=NULL && atual->GetInfo() < elem)  
            {  
                ant=atual;  
                atual=atual->GetProx();  
            }  

            if(ant==NULL) //inicio  
            {  
                novo->SetProx(inicio);  
                inicio=novo;  
            }  
            else //meio ou fim  
            {  
                ant->SetProx(novo);  
                novo->SetProx(atual);  
            }  
        }  
        this->tam++;
        return true;
    }  

    bool remove(const tipo& elem)    
    {    
        No <tipo> *ant=NULL,*atual;    
          
        if(empty())    
            return false;     
  
        atual = inicio;    
  
        while( atual && (atual->GetInfo() < elem))    
        {    
            ant=atual;    
            atual=atual->GetProx();    
        }    
  
        if(atual!=NULL && atual->GetInfo() == elem)    
        {    
            if(ant==NULL)//inicio    
                inicio=atual->GetProx();    
            else//meio ou fim    
                ant->GetProx()=atual->GetProx();    
            delete atual;  
            this->tam--;  
            return true;    
        }    
  
        return false; //nao existe    
    }   

    bool busca(const tipo& elem) 
    {
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           if(aux->GetInfo() == elem)
               return true;
        return false;
    }

    tipo get(const int& pos) const
    {
        int posAux = 1;
        tipo auxT;
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           if(posAux == pos)
               return auxT = aux->GetProx();
           posAux++;
        return auxT = NULL;
    }

    const int& tamanho() const
    {
        int posAux = 0;
        No<tipo>* aux;
        for(aux = inicio; aux != NULL; aux = aux->GetProx())
           posAux++;
        return posAux;
    }

    No<tipo>* GetInicio() const
    {
        return inicio;
    }

};

#endif	/* LISTA_H */

As outras classes continuam as mesmas.

Fiz o seguinte método principal:

/* 
 * File:   main.cpp
 * Author: higornucci
 *
 * Created on 26 de Agosto de 2011, 20:31
 */

#include <iostream>
#include <string>

#include "Funcionario.h"
#include "Usuario.h"
#include "Lista.h"
#include "CadastrarFuncionario.h"

/*
 * 
 */
int main(int argc, char** argv) {

    Funcionario func1;
    func1.SetId(1);
    func1.SetNome("Higor");
    func1.SetCpf("123445");
    func1.SetEndereco("Rua Da Saudade, 012");
    func1.SetCidade("Dourados");
    func1.SetEstado("MS");
    
    Usuario user1;
    user1.SetId(1);
    user1.SetLogin("higornucci");
    user1.SetSenha("1234");
    user1.SetFuncionario(func1);
    
    Lista<Funcionario> listaFunc;
    listaFunc.adiciona(func1);
    listaFunc.remove(func1);
    
    Lista<Usuario> listaUser;
    listaUser.adiciona(user1);
    
    CadastrarFuncionario cf(listaFunc);
    cf.adiciona();
    cf.excluir("Higor");
    
    for(No<Usuario>* p = listaUser.GetInicio();
            p != NULL;
            p = p->GetProx()) {
        p->GetInfo().imprimir();
        cout << "\n-------------------------------------------------\n";
    }
    
    listaFunc.~Lista();
    listaUser.~Lista();
    return 0;
}

Não consigo achar a fonte desse erro. Alguém sabe?

V

Você não pode atribuir um valor para o retorno de um método (lvalue é o que está do lado esquerdo da expressão):
No lugar disso:

Deve ser isso:

H

Eu li tantas vezes e não reparei que estava usando um método GET.

Obrigado pela observação.

Criado 26 de agosto de 2011
Ultima resposta 18 de set. de 2011
Respostas 9
Participantes 2