Как я могу запретить простое назначение MyClass = int? - PullRequest
0 голосов
/ 20 сентября 2018

если у меня есть класс с такими атрибутами, как это:

struct MyClass {
   double **arowofpointers;
   int capacity;
};

Теперь, если задача говорит "убедитесь, что эта строка кода в основной функции допустима:

MyClass a(10); //makes a variable whose type is MyClass that has the capacity of 10

Но убедитесь, что следующая строка кода в основной функции недопустима:

MyClass a=10;

Тем не менее, следующая строка вашего кода в основной функции должна быть допустимой:

a=b+c;

где, a, b и c - все переменные, тип которых - MyClass.

Какие конструкторы я должен создать? Что-то, что я должен установить при удалении или что-то еще?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

MyClass a(10); требует конструктор преобразования, который принимает целое число в качестве входных данных.Чтобы предотвратить MyClass a=10;, для этого конструктора explicit.

a = b + c; требуется operator+ для объединения двух MyClass объектов и operator= для назначения одного MyClass объекта другому.Если вы хотите поддерживать инициализации, такие как MyClass a = b;, MyClass a = b + c; и т. Д., Вам также понадобится конструктор копирования.

И не забудьте деструктор.

Итак, вывам понадобятся эти конструкторы и операторы в вашем struct:

struct MyClass
{
private:
   double **arowofpointers;
   int capacity;

public:
   // default constructor
   MyClass();

   // conversion constructor
   explicit MyClass(int cap);

   // copy constructor
   MyClass(const MyClass &src);

   // move constructor (C++11 and later only, optional but recommended)
   MyClass(MyClass &&src);

   // destructor
   ~MyClass();

   // copy assignment operator
   MyClass& operator=(const MyClass &rhs);

   // move assignment operator(C++11 and later only, optional but recommended)
   MyClass& operator=(MyClass &&rhs);

   // concatenation operator overload
   MyClass operator+(const MyClass &rhs) const;

   // compound concatenation assignment operator (optional)
   MyClass& operator+=(const MyClass &rhs);

   // swap helper
   void swap(MyClass &other);
};

// std::swap() overload
void swap(MyClass &lhs, MyClass &rhs);

Где реализации могут выглядеть примерно так:

#include <algorithm>

MyClass::MyClass()
    : arowofpointers(nullptr), capacity(0)
{
}

MyClass::MyClass(int cap)
    : arowofpointers(new double*[cap]), capacity(cap)
{
    std::fill_n(arowofpointers, capacity, nullptr);
}

MyClass::MyClass(const MyClass &src)
    : arowofpointers(new double*[src.capacity]), capacity(src.capacity)
{
    std::copy(src.arowofpointers, src.arowofpointers + capacity, arowofpointers);
}

MyClass::MyClass(MyClass &&src)
    : arowofpointers(nullptr), capacity(0)
{
    src.swap(*this);
}

MyClass::~MyClass()
{
    delete[] arowofpointers;
}

MyClass& MyClass::operator=(const MyClass &rhs)
{
    if (&rhs != this)
        MyClass(rhs).swap(*this);
    return *this;
}

MyClass& MyClass::operator=(MyClass &&rhs)
{
    MyClass tmp(std::move(*this));
    rhs.swap(*this);
    return *this;
}

MyClass MyClass::operator+(const MyClass &rhs) const
{
    MyClass tmp(capacity + rhs.capacity);
    std::copy(arowofpointers, arowofpointers + capacity, tmp.arowofpointers);
    std::copy(rhs.arowofpointers, rhs.arowofpointers + rhs.capacity, tmp.arowofpointers + capacity);
    return tmp;
}

MyClass& MyClass::operator+=(const MyClass &rhs)
{
    MyClass tmp = *this + rhs;
    tmp.swap(*this);
    return *this;
}

void swap(MyClass &lhs, MyClass &rhs)
{
    lhs.swap(rhs);
}

При этом, если вместо этого вы используете std::vector, тогда вам не нужно обрабатывать большую часть этого самостоятельно, позвольте компилятору и STL выполнить тяжелую работу за вас:

#include <vector>

struct MyClass
{
private:
   std::vector<double*> arowofpointers;

public:
   MyClass();
   explicit MyClass(int cap);

   MyClass operator+(const MyClass &rhs) const;

   MyClass& operator+=(const MyClass &rhs);

   void swap(MyClass &other);
};

void swap(MyClass &lhs, MyClass &rhs);

#include <algorithm>

MyClass::MyClass()
    : arowofpointers()
{
}

MyClass::MyClass(int cap)
    : arowofpointers(cap, nullptr)
{
}

MyClass MyClass::operator+(const MyClass &rhs) const
{
    MyClass tmp(arowofpointers.capacity() + rhs.arowofpointers.capacity());
    tmp.arowofpointers.insert(tmp.arowofpointers.end(), arowofpointers.begin(), arowofpointers.end();
    tmp.arowofpointers.insert(tmp.arowofpointers.end(), rhs.arowofpointers.begin(), rhs.arowofpointers.end();
    return tmp;
}

MyClass& MyClass::operator+=(const MyClass &rhs)
{
    MyClass tmp = *this + rhs;
    tmp.swap(*this);
    return *this;
}

void swap(MyClass &lhs, MyClass &rhs)
{
    lhs.swap(rhs);
}
0 голосов
/ 20 сентября 2018

Для создания экземпляра типа MyClass следующим образом

MyClass a(10);

требуется конструктор, который принимает целочисленный параметр:

class MyClass {
  public:
    MyClass(int param);

  // ...
};

Но так как конструкторы неявны по умолчанию (чток сожалению), учитывая MyClass a = 10;, вам нужно сделать это явно:

// This constructor must be called explicitly via MyClass(int)
explicit MyClass(int param);

Это заставит компилятор жаловаться, когда он встречает MyClass a = 10;.

Для операторской части вашеговопрос, возможно, вы захотите взглянуть на этот (часть "Арифметические операторы").

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...