Problem with operator overload

Asked

Viewed 420 times

2

Errors occur when I step the class object Name_pairs by the exit operator << and by the comparative operator ==.

Header:

    class Name_pairs
    {
    public:
        void read_names(); 
        void read_ages();
        void print() const; 
        void sort(); 
        const std::vector<std::string>& get_name() const { return name; } 
        const std::vector<double>& get_age() const { return age; }    
    private:
        std::vector<std::string>name; 
        std::vector<double>age;     
    };
}

Main.cpp:

int main()
{
    Name_pairs objeto;
    objeto.read_names();
    objeto.read_ages();
    objeto.sort();
    objeto.print();

    Name_pairs objetoDois;
    objetoDois.read_names();
    objetoDois.read_ages();
    objetoDois.sort();
    objetoDois.print();

    if(objeto == objetoDois) cout << "iguais!"; // erro no operador == ;
    else cout << "não são iguais!";
    cout << objeto;  // erro no operador << ;

    system("pause");
    return 0;
}

cpp of definitions:

    void Name_pairs::read_names()
    {
        cout << "Entre com os nomes desejados, digite 'SemNome' para               finalizar a lista." << endl;
        string NomesVetor; 

        while (cin >> NomesVetor && NomesVetor != "SemNome")
        {
            for (size_t x = 0; x < name.size(); ++x) // confere se há nomes duplicados 
            {
                if (name[x] == NomesVetor) cout << "Nome repetido." << endl;
            }

            name.push_back(NomesVetor);
        }
    }

    void Name_pairs::read_ages()
    {
        for (size_t x = 0; x < name.size(); ++x)
        {
            cout << "Idade de " << name[x] << ": " << endl;
            double IdadesVetor; 
            cin >> IdadesVetor;
            age.push_back(IdadesVetor);
        }
    }

std::ostream& operator<<(std::ostream& os, const Name_pairs& np)
{
    for (size_t x = 0; x < np.get_name().size(); ++x)
        os << '(' << np.get_name()[x] << ', ' << np.get_age()[x] << ')' << endl;

    return os;

}

 bool operator==(const Name_pairs& a, const Name_pairs& b )
{
    if(a.get_name().size() != b.get_name().size() || a.get_age().size() != b.get_age().size())
    return false;

    for (size_t x = 0; x <a.get_name().size(); ++x)
    {
        if (a.get_name()[x] != b.get_name()[x]) return false;
        if (a.get_age()[x] != b.get_age()[x]) return false;
    }
    return true;
}

bool operator!=(const Name_pairs& a, const Name_pairs& b)
{
    return !(a == b);
}

Remembering that: The code compiles if removed

 if(objeto == objetodois)cout << "iguais!"; // erro no operador ==
        else cout << "não são iguais!";
        cout << objeto;  // erro no operador << 

of main.

  • Put more excerpts from main(), you can even tell the type of variables used only with this excerpt.

  • Okay, I edited with the main.

  • This code does not even compile. It has primary errors. Put a [mcve], it will not do to play random codes, this will not help you.

  • Let me explain further. As I said, the code compiles but the error only appears if I call the << and the == in the main, I passed the type I want to compare, in case two classes with two vectors: a string and a double in each. And I also showed you the overload function. It was not the intention if I passed the impression of "copy paste and solve my problems", I will also show the functions to fill my vectors, if it helps to understand the functioning.

  • When you do a [mcve] you warn me, for now you can not answer, reaches the point of using variables that do not exist, this code is not real.

  • I noticed some mistakes that you had commented, sorry for them. Anyway, the only thing I didn’t put in was the Sort() function that only serves what her name suggests, if something is missing please let me know.

Show 1 more comment

1 answer

1


Marv,

Your code isn’t complete, so it’s impossible to evaluate it. Still I exemplify below the implementation of both operators in any class.

It is important to remember that for the Compile example the Operator<< method should be declared as "Friend" of the class, allowing an object of the class to be passed by reference to the standard output (alias Cout).

#include <iostream>
#include <string>

class Classe
{
public:
    std::string texto;
    int numero;

    bool operator==(const Classe& cmp)
    {
        return this->numero == cmp.numero && this->texto == cmp.texto;
    }

    friend std::ostream& operator<<(std::ostream& os, const Classe& obj)
    {
        os << obj.texto;
        return os;
    }
};

int main()
{
    Classe objeto_1, objeto_2;

    objeto_1.numero = 1;
    objeto_1.texto = "Objeto 1";

    objeto_2.numero = 2;
    objeto_2.texto = "Objeto 2";

    if (objeto_1 == objeto_2)
    {
        std::cout << "Os objetos comparados são iguais." << std::endl;
        return 1;
    }

    std::cout << objeto_1 << " é diferente de " << objeto_2 << std::endl;
    return 0;
}

I hope I could help you.

Edited:

I managed to understand the code posted and make the modifications so that it works correctly.

The "Friend" modifier when used makes the function an "aggregate" of the class rather than a member, which does not allow the syntax specified in my answer above.

Removing this modifier uses only 1 parameter for == and != this parameter is compared to the value pointed by the "this" pointer of the current class, as the code demonstrates below:

#include <iosfwd>
#include <string>
#include <vector>
#include <iostream>

class Name_pairs
{
public:
    void read_names();
    void read_ages();
    void print() const;
    void sort();

    const std::vector<std::string>& get_name() const
    {
        return name;
    }

    const std::vector<double>& get_age() const
    {
        return age;
    }

    bool operator==(const Name_pairs& a)
    {
        if (a.get_name().size() != this->get_name().size() || a.get_age().size() != this->get_age().size())
            return false;

        for (size_t x = 0; x < a.get_name().size(); ++x)
        {
            if (a.get_name()[x] != this->get_name()[x]) return false;
            if (a.get_age()[x] != this->get_age()[x]) return false;
        }
        return true;
    }

    bool operator!=(const Name_pairs& a)
    {
        return !((*this) == a);
    }

    std::ostream& operator<<(std::ostream& os)
    {
        for (size_t x = 0; x < this->get_name().size(); ++x)
            os << '(' << this->get_name()[x] << ", " << this->get_age()[x] << ')' << std::endl;

        return os;
    }

private:
    std::vector<std::string>name;
    std::vector<double>age;
};

void Name_pairs::read_names()
{
    std::cout << "Entre com os nomes desejados, digite 'SemNome' para               finalizar a lista." << std::endl;
    std::string NomesVetor;

    while (std::cin >> NomesVetor && NomesVetor != "SemNome")
    {
        for (size_t x = 0; x < name.size(); ++x) // confere se há nomes duplicados
        {
            if (name[x] == NomesVetor) std::cout << "Nome repetido." << std::endl;
        }

        name.push_back(NomesVetor);
    }
}

void Name_pairs::read_ages()
{
    for (size_t x = 0; x < name.size(); ++x)
    {
        std::cout << "Idade de " << name[x] << ": " << std::endl;
        double IdadesVetor;
        std::cin >> IdadesVetor;
        age.push_back(IdadesVetor);
    }
}

It was possible to compile and use normally (except for the absence of some functions implementation) the class with the code posted.

  • Opa, thank you so much for the "Friend" tip, it was very helpful. As for the post, I’ve edited a few times and had forgotten to put the code of the class, of those there I just left out the functions that do not need to be implemented for the part I need to happen. I need to compare the age vector and other names of an object with two other objects of the same class. Anyway, it is possible?

  • 1

    Yes, it is possible... it will be necessary to implement the comparison between them through the Operator== manually. The operator will only facilitate work once implemented to compare two objects of the same type.

  • Yes yes! Precisely, I did it with the fors to make it clear but still I get this mistake.

  • 1

    I edited my answer again, with the necessary adjustments for your code to work, give a check... I hope it was useful.

  • 2

    @Marv, it is worth noting that some parts of its implementation are more complicated than necessary. The std::vector already defines a comparison operator and therefore just compare the vectors directly and do not go through comparing their values one by one. Already in the function read_names, you can replace your loop that checks if the name already exists by using the std::find declared in the archive algorithm.

  • 2

    @Marv, note that it is not necessary to declare operators as friend or class members in their case since they depend only on the public interface of their class. Your code was correct, but you had not declared the operators in the header so the function main I couldn’t find them. Whenever possible, prefer to declare operators as free functions because this way you minimize the dependency on the private values of your class and in the case of symmetric operators such as the comparison you avoid possible problems where a == b is not equivalent to b == a due to conversions.

  • Hey, thanks for the tips. Yes, I know that many member functions is not a good thing, I had tried to do in some ways but I had not succeeded, I am quite beginner yet. This vector will be very useful.

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.