Скопируйте конструктор и перегруженный оператор сложения - PullRequest
0 голосов
/ 10 июня 2018

Я рассматриваю перегрузку операторов в C ++.Ради интереса я реализую класс BigInt.

Первый оператор, который я хочу перегрузить для него, это оператор сложения .Я решил перегрузить этот оператор как функцию, не являющуюся другом.Вот MWE этого кода:

#include <cassert>
#include <iostream>
#include <string>

class BigInt{
 public:
  friend BigInt operator+(const BigInt &bi1, const BigInt &bi2);

  BigInt() {}
  explicit BigInt(const std::string &in) {
    if (in.size() != 0) {
      for (auto cc = in.rbegin(); cc != in.rend(); ++cc) {
        value_.push_back(*cc);
      }
    }
  }
  std::string value() {
    std::string actual_value{};  // Reversed string.
    for (auto cc = value_.rbegin(); cc != value_.rend(); ++cc) {
      actual_value.push_back(*cc);
    }
    return actual_value;
  }

 private:
  std::string value_;  // String of digits as characters.
};

BigInt operator+(const BigInt &bi1, const BigInt &bi2) {
  BigInt result{};

  result.value_ = "4421";
  return result;
}

int main() {
  std::cout << "Test addition operator... ";
  std::string number{"1234"};  // Number 1,234.
  BigInt mm(number);
  std::string number_ten{"10"};  // Number 10.
  BigInt nn(number_ten);

  BigInt mm_nn = mm + nn;

  std::string expected_result{"1244"};  // 1,234 + 10 = 1,244.
  assert(mm_nn.value() == expected_result);
  std::cout << "ok." << std::endl;
}

Этот код имитирует поведение сложения.Он компилируется и запускается.Тем не менее, когда я добавляю конструктор копирования для класса BigInt, этот код перестает работать.Т.е. если я добавлю это в объявление класса:

explicit BigInt(const BigInt &in): value_(in.value_) {}

Код даже не скомпилируется.Функция сложения в кодированном виде возвращает копию созданного экземпляра BigInt.Для этого должен быть определен конструктор копирования.Если я не определю это сам, то компилятор сделает это.Что производит компилятор, который я не создаю с добавленным конструктором копирования?Вот ошибка компиляции, которую я получаю:

$ g++ -std=c++14 -g mwe.cpp 
mwe.cpp: In function ‘BigInt operator+(const BigInt&, const BigInt&)’:
mwe.cpp:34:10: error: no matching function for call to ‘BigInt::BigInt(BigInt&)’
   return result;
          ^
mwe.cpp:9:3: note: candidate: BigInt::BigInt()
   BigInt() {}
   ^
mwe.cpp:9:3: note:   candidate expects 0 arguments, 1 provided
mwe.cpp: In function ‘int main()’:
mwe.cpp:44:23: error: no matching function for call to ‘BigInt::BigInt(BigInt)’
   BigInt mm_nn = mm + nn;
                       ^
mwe.cpp:9:3: note: candidate: BigInt::BigInt()
   BigInt() {}
   ^
mwe.cpp:9:3: note:   candidate expects 0 arguments, 1 provided

Похоже, что компилятор ожидает конструктор копирования, который я не предоставил.Теперь ... Если я удаляю ключевое слово explicit, все работает.Однако я видел реализации с явным конструктором копирования, например: Явный конструктор копирования

Чего мне не хватает?Почему я не могу сделать этот конструктор копирования явным при перегрузке оператора сложения?Должны ли вообще конструкторы копирования быть явными?

1 Ответ

0 голосов
/ 10 июня 2018

Создание конструктора копирования explicit не имеет смысла.Удалите его.

BigInt(const BigInt &in): value_(in.value_) {}

Концептуальная проблема с explicit Конструктором копирования

Создание конструктора копирования explicit делает невозможным возврат объекта из функции.

Давайте упростим ваш код до следующего:

struct BigInt
{
   BigInt() {}
   explicit BigInt(const BigInt &in) {}
};

BigInt operator+(const BigInt &bi1, const BigInt &bi2)
{
   BigInt result;
   return result;
}

int main() {}

В строке return result компилятор полагается на конструктор копирования для возврата объекта.Когда конструктор копирования является явным, BigInt не может быть создан в качестве возвращаемого значения.

Попытка использовать:

BigInt operator+(const BigInt &bi1, const BigInt &bi2)
{
   BigInt result;
   return BigInt(result);
}

бесполезна, поскольку это эквивалентно:

BigInt operator+(const BigInt &bi1, const BigInt &bi2)
{
   BigInt result;
   BigInt result1(result);
   return result1;
}

Проблема сохраняется, независимо от того, что вы делаете в функции.

...