Problem with struct in C++

What kind of error or omission am I making in the code?

Specifically in the main sentence if. Error which I have solved by comparing one by one the results, which would be problematic when I have to compare more than 3 variables.

#include<iostream>
using namespace std;

struct persona{
    string nombre, pat, mat;
};

int main(){
    persona a,b;

    b.nombre = "luz";
    b.pat = "dia";
    b.mat = "noche";

    cout<<"ingrese su nombre : ";
    cin>>a.nombre;
    cout<<"ingrese su apellido paterno : ";
    cin>>a.pat;
    cout<<"ingrese su apellido materno : ";
    cin>>a.mat;

    if(a == b)cout<<"son la misma persona.";//aqui tengo el problema. Siento de que se me olvida algo...
        else cout<<"son diferentes personas.";

Here is the way I solved it.

if(a.nombre == b.nombre){
   if(a.pat == b.pat){
      if(a.mat == b.mat)cout<<"son la misma persona.";
   }
   else cout<<"son diferentes personas.";
}
else cout<<"son diferentes personas.";
 3
Author: Shaz, 2016-06-22

3 answers

In C++, no comparison operators are generated for user-defined non-arithmetic types1, whether they are struct, class or union; so the programmer must provide such operator, for this there are two options:

Member operator.

As part of your structure interface, you can add a comparison operator:

struct persona{
    string nombre, pat, mat;

    bool operator ==(const persona &otra_persona) const{
        return nombre == otra_persona.nombre &&
               pat    == otra_persona.pat &&
               mat    == otra_persona.mat;
    }

};

Adding this member operator tells your compiler how you want it to compare for fairness the current instance of the structure persona when compared against another of the same type, the parameter of the bool operator == will be that which is put to the right of a == when on the left there is a structure persona.

Free operator.

You can specify how to compare user-defined types without modifying their interface, by adding a free function that receives as parameters the types to be compared, as already suggested Arnau CastellvĂ­ :

bool operator ==(const persona &p1, const persona &p2)
{ 
    return (p1.nombre == p2.nombre &&
            p1.pat    == p2.pat &&
            p1.mat    == p2.mat);
}

For my part I prefer to add the qualifier const in this operator because this type of operation does not modify (nor should modify) the operands.

With this free operator you tell your compiler how you want two instances of the persona structure to be compared for equity when it is to the left and right of a ==.

Which one to choose?.

The member operator and the free operator have differences that worth mentioning:

  • member : requires modifying the interface of the object, the owner type of the operator member will always be to the left of the operator. You have access to the object's private members.
  • Free : does not require modifying the interface of the object, the order of the operands can be defined in the comparison operation. You don't have access to the object's private members2.

For understanding these differences, I will add another class:

struct empleado{
    persona per;
    string departamento;

    bool operator ==(const persona &una_persona){
        return per == una_persona;
    }
};

With this comparison operator in empleado we will have the possibility to compare employees with people but not the other way around :

persona a{"luz", "dia", "noche"}, b{"K'Thulu", "Ia", "Nfang"};
empleado e{ a, "Dominio Mundial" };

bool resultado1 = (e == a); // Verdadero!
bool resultado2 = (b == e); // Error! No se puede comparar persona contra empleado

Since the member operator requires the operator's owner type to be always to the left of the comparison, people against employees cannot be compared... but adding a free operator:

bool operator ==(const persona &una_persona, const empleado &un_empleado){
    return una_persona == un_empleado.per;
}

Can already compare person (left of comparison, first parameter of the free operator) against employees (comparison right, second parameter of the free operator):

bool resultado1 = (e == a); // Verdadero!
bool resultado2 = (b == e); // Falso!

In your specific case it is indifferent the use of a member or free operator, but at other times you will have to choose between one or the other... I would personally opt for the free operator since it will allow you to use the class in containers (which would not allow the free comparison function that suguiere the salty NaCl) without pollute the interface of the object.


1since the enumerated are user-defined types but their underlying type is arithmetic, the compiler compares their value without requiring comparison operator.

2unless it is defined as a friend function.

 4
Author: PaperBirdMaster, 2020-06-11 10:54:57

I think what you are looking for is called "Operator overhead"

Would be redefining the == operator for that type of object, something like this:

bool operator == (persona &p1,persona &p2)
{ 
    return (p1.nombre==p2.nombre&&p1.pat==p2.pat&&p1.mat==p2.mat);
}

Google it, it should not be difficult to find information.

 2
Author: Arnau CastellvĂ­, 2016-06-23 01:18:30

Let's avoid a complicated issue like operator overhead and create a function that helps us evaluate each value in the struct:

bool equals(persona _a, persona _b)
{
    return (_a.nombre == _b.nombre) 
        && (_a.mat == _b.mat)
        && (_a.pat == _b.pat);
     // && (_a.<otravariable> == _b.<otravariable>)
}

As can be seen, we are creating a function of type bool that evaluates us every member within the instance of type persona that we send.

To check that all members are the same, the operator is used&& (y) to bind conditions.

Applied to your code:

if(equals(a, b)) cout<<"son la misma persona."; // No deberia haber error...

Whereas with operator overhead, it's something like What Arnau has mentioned.

In the end you will always compare each of the values manually, but there are processes that allow the simplification of such comparison.

Hope I helped you!

 2
Author: NaCl, 2016-06-23 01:20:27