Pergunta

I have a class with two vectors: an int and an Str. Now I want to define a copy constructor so that the order of elements is reversed; e.g. if a=(1,Hello),(2,World) and I write auto b=a; I get b=(2,world),(1,hello). Which is working perfectly. The issue I am having is overloading the = operator so that the copy constructor is utilized. Here is my Class plus copy constructor:

class grade
{
  private:
    static int copies;
    std::vector<int> i;
    std::vector<std::string> s;

  public:
    grade() {copies++;};
    grade (int , std::string );
    void printval();
    void adder(int , std::string );
    int getcount();

    grade(grade & obj)
    {
        std::vector<std::string>::reverse_iterator strIt = obj.s.rbegin();
        for (std::vector<int>::reverse_iterator numIt=obj.i.rbegin();
             numIt!=obj.i.rend(); ++numIt)
        {
            this->adder(*numIt, *strIt);
            strIt++;
        }

    }
    grade operator =(grade );
};

When I overload the = operator the constructor is called and the trouble is that the valur is not passed to the LHS variable. Here is the overloaded =.

grade grade::operator=(grade cpy)
{
    grade newer = cpy; //Calls the copy constructor as expected
    return cpy;        //No error but blank value is returned to the LHS variable.
}

My main function is :

int main()
{
    grade c2(1,"Hello");
    grade c1;

    c2.adder(4,"World");
    c2.printval();
    std::cout<<std::endl;
    grade c3 = c2;
    c3.printval();
    std::cout<<std::endl;
    c1 = c2;
    std::cout<<std::endl;
    c1.printval();

    return 0;
}

Why does c1 remain blank??

Foi útil?

Solução 2

You asked: Why does c1 remain blank??

The answer is that the assignment operator does not modify the object itself. Here's your code:

grade grade::operator=(grade cpy)
{
  grade newer=cpy; //Calls the copy constructor as expected
  return cpy; //No error but blank value is returned to the LHS variable.
}

The method returns a copy of the input parameter cpy but does not modify the current instance. When this method is executing, *this is the "LHS variable", and it's not being modified at all. Within this method (operator overload, you need to actually modify the member variables of the current instance!

Outras dicas

The easiest way to implement the assigment operator is the copy and swap idiom:

grade& operator=( grade other )
{
   swap( *this , other );
   return *this;
}

Where swap is a function which takes two grades and swaps its values:

void swap( grade& lhs , grade& rhs )
{
    using std::swap;

    swap( lhs.first_member  , rhs.first_member  );
    swap( lhs.second_member , rhs.second_member );
    swap( lhs.third_member  , rhs.third_member  );
    ...
}

Note that swap() is an overload/specialization of std::swap(). std::swap() uses the assigment operator to perform the swaping by default, so if you use it you lead into infinite recursion. What you have to do is to write your own swap overload which performs member by member swapping (As in the example above).

Note that you should use unqualified swap() to not disable ADL, and let the compiler find the custom swap() overload of the members (If they provide one) or the Standard Library version instead.

What you want is the copy-and-swap idiom:

#include <algorithm>
grade &grade::operator=( grade cpy ) {
    using std::swap;
    swap( i, cpy.i );
    swap( s, cpy.s );
    return *this;
}

Change your copy constructor and your assignment operator as follows:

grade::grade(const grade& cpy)
{
    *this = cpy;
}

grade& grade::operator=(const grade& cpy)
{
    if (this == &cpy)
        return *this;

    std::vector<std::string>::reverse_iterator strIt = cpy.s.rbegin();
    for (std::vector<int>::reverse_iterator numIt=cpy.i.rbegin();numIt!=cpy.i.rend();++numIt)
    {
        this->adder(*numIt, *strIt);
        strIt++;
    }

    return *this;
}

And as a general scheme:

object::object(const object& input)
{
    *this = input;
}

object& object::operator=(const object& input)
{
    if (this == &input)
        return *this;

    Deallocate();
    Allocate(input);
    Initialize(input);

    return *this;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top