Я запутался в использовании перегрузки оператора для '<<' в C ++ - PullRequest
2 голосов
/ 09 марта 2020

Для этого примера я собираюсь просто использовать два бессмысленных объекта класса - X и Y. На самом деле все, что имеет значение, это X.

X содержит несколько функций-членов: массив указателей Y и заголовок, который называет объект типа X.

Во время построения единственное, что нужно, это имя объекта класса. er go, объявленный как

X newList("ListTitle")

Теперь, по логике вещей, вы могли бы подумать, что способ добавления данных в массив указателей будет что-то вроде

for(int x = 0; each item passed){
 newList.Array[x] = itemPassed[x]; 

Однако я видел задания, которые хотят, чтобы мы делали это как-то странно. нас просят перегрузить '<<', чтобы он каким-то образом инициализировал массив указателей, написав </p>

newList <<"Item 1"<<"item 2"<<"item3";

Является ли этот метод добавления вещей к членам класса законно используемой вещью в реальной сценарий работы? Когда я смотрю на это, это не кажется синтаксически правильным и чертовски ненужным. Я просто пытаюсь выяснить, действительно ли это то, что я когда-либо на самом деле использовал бы вне школьных классов.

Ответы [ 4 ]

2 голосов
/ 09 марта 2020

Является ли этот метод добавления вещей членам класса законно используемым в реальном сценарии работы? Когда я смотрю на это, это не кажется синтаксически правильным и чертовски ненужным. Я просто пытаюсь выяснить, использовал ли я это когда-либо вне школьных классов.

Некоторые возможности C ++ связаны с возможностью операторов перегрузки . Как всегда, с великой силой приходит большая ответственность. Операторы могут быть перегружены, чтобы сделать очевидное, например, никто не будет удивлен кодом, подобным этому

Matrix a{ {1,2},{2,3} };
Matrix c = a + a;

Возможно, вы даже не заметите, что + здесь пользовательский оператор. C ++ сам по себе не может добавить две матрицы. Недостатком перегрузки операторов является то, что вы можете перегружать их, чтобы делать в основном все, что угодно, а иногда это не так очевидно. Граница между хорошей перегрузкой оператора и той, которая приводит к запутанному коду, тонкая.

Что касается вашего конкретного примера, то это шаблон, который вы также можете найти в другом месте. Eigen - это хорошо известная библиотека алгебры. Пример из их документации:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
int main()
{
  Matrix2d a;
  a << 1, 2,
       3, 4;
  MatrixXd b(2,2);
  b << 2, 3,
       1, 4;
  std::cout << "a + b =\n" << a + b << std::endl;
  std::cout << "a - b =\n" << a - b << std::endl;
  std::cout << "Doing a += b;" << std::endl;
  a += b;
  std::cout << "Now a =\n" << a << std::endl;
  Vector3d v(1,2,3);
  Vector3d w(1,0,0);
  std::cout << "-v + w - v =\n" << -v + w - v << std::endl;
}

Обратите внимание на использование оператора << для установки элементов матрицы. Они добавляют некоторый оператор запятой voodoo, но использование оператора << довольно похоже на то, что вы должны реализовать.

Является ли этот метод добавления вещей в члены класса законно используемым вещь в реальном сценарии работы?

Да. Использование operator<< для «вставки» элементов в объект совершенно законно. Вы увидите такое использование перегрузки операторов в различных библиотеках. Если оператор используется таким образом, конечно, это требует надлежащей документации, потому что знание языка C ++ недостаточно, чтобы знать, что на самом деле означает оператор в определенном контексте.

1 голос
/ 09 марта 2020

Является ли этот метод добавления вещей членам класса законно используемым в реальном сценарии работы?

Вероятно, нет. Во всяком случае, в большинстве случаев.

Очереди и стеки могут найти применение, где << означает добавление в очередь или стек, а >> означает чтение и удаление из очереди или стека.

Другие возможные варианты использования: если вы найдете причину написать свой собственный поток , вы можете сохранить данные как std::vector и использовать оператор << для добавления символа данные к нему.

В целом, однако, я бы не рекомендовал использовать оператор << для подобных вещей. Его слишком легко спутать с операторами std::ostream и std::istream << и >>. Большинство людей, читающих ваш код, могут легко понять его. Кроме того, существуют лучшие способы инициализации данных, такие как списки инициализаторов .

1 голос
/ 09 марта 2020

Вы можете создать функцию для добавления новых объектов Y в массив X. Каждый раз, когда вызывается функция, она возвращает один и тот же объект x, поэтому функцию можно вызывать снова с тем же x.

X& operator<<(X& x, const char * s){
  x.Array.push_back(new Y(s));
  return x;
}

(push_back - это способ добавления элемента с помощью std :: vector, или emplace_back)

Это похоже на работу std :: cout.

0 голосов
/ 09 марта 2020

Технически вполне возможно работать так, как вы собираетесь, и ответ Квентина объясняет, как это сделать.

Кроме того, обычной практикой является использование operator<< в качестве средства вставки потока для вывода данных (на консоль, файл, но также и в памяти в случае строковых потоков). Но с помощью потокового интерфейса ваши пользователи могут на законных основаниях ожидать, что вы реализуете потоковое поведение последовательно, чтобы они могли использовать некоторые параметры форматирования, такие как setw или даже endl.

Но это потоковое использование это исключение, а не правило. Он не соответствует обычному семанту c оператора сдвига <<, который, как ожидается, не окажет каких-либо побочных эффектов на свои операнды. Поэтому, если X не представляет какой-то вид потоков, я бы советовал против этого и рекомендовал бы вместо этого использовать метод цепочки методов:

X.push(Y1).push(Y2).push(Y3); 

Вы бы определили push() (или append или add ) точно так, как предложил Квентин operator<<, за исключением названия функции.

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