У меня есть класс с двумя векторами: int
и Str
, Теперь я хочу определить конструктор копирования, чтобы порядок элементов был обратным; например если a=(1,Hello),(2,World)
и я пишу auto b=a;
я получил b=(2,world),(1,hello)
, Который работает отлично. Проблема, которую я имею, перегружает =
оператор, так что конструктор копирования используется. Вот мой класс плюс конструктор копирования:
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 );
};
Когда я перегружаю =
оператор конструктор вызывается и проблема в том, что valur не передается в переменную LHS. Вот перегружен =
,
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.
}
Моя основная функция:
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;
}
Почему c1
оставить пустым ??
Вы спрашивали: Why does c1 remain blank??
Ответ в том, что оператор присваивания не изменяет сам объект. Вот ваш код:
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.
}
Метод возвращается копия входного параметра cpy
но не изменяет текущий экземпляр. Когда этот метод выполняется, *this
является «переменная LHS», и она не изменяется вообще. В этом методе (перегрузка оператора) вам необходимо изменить переменные-члены текущего экземпляра!
Самый простой способ реализовать оператор присваивания — это скопировать и поменять идиому:
grade& operator=( grade other )
{
swap( *this , other );
return *this;
}
Где своп это функция, которая занимает два grade
s и меняет его значения:
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 );
...
}
Обратите внимание, что swap()
это перегрузка / специализация std::swap()
, std::swap()
по умолчанию использует оператор назначения для выполнения подкачки, поэтому, если вы используете его, вы ведете к бесконечной рекурсии. Что вам нужно сделать, это написать свою собственную перегрузку подкачки, которая выполняет замену элементов на элементы (как в примере выше).
Обратите внимание, что вы должны использовать неквалифицированную swap()
не отключать ADL и позволить компилятору найти кастом swap()
перегрузка членов (если они предоставляют) или версия стандартной библиотеки.
То, что вы хотите, это идиома копирования и обмена:
#include <algorithm>
grade &grade::operator=( grade cpy ) {
using std::swap;
swap( i, cpy.i );
swap( s, cpy.s );
return *this;
}
Измените ваш конструктор копирования и ваш оператор присваивания следующим образом:
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;
}
И как общая схема:
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;
}