оператор сдвига перегрузки & lt; & lt; разрешить цепочку

Я борюсь с перегрузкой оператора, так как хочу, чтобы он позволял цепочку

class A{
int a;
public:
void doSomething(char *str);
A operator<<(char *str);
}

Итак, у меня есть этот класс, и я могу взять строку и сделать что-то, что не важно для этого вопроса.

То, что я теперь мог сделать, это

A *counter = new A();
counter->doSomething("hello");

Если я реализую перегруженный оператор сдвига

A A::operator<<(char *str)
{
this->doSomething(str);
return this;
}

Я могу написать это так

A *counter = new A();
(*counter) << "hello";

Я надеюсь, что я не ошибся здесь, потому что теперь мне интересно, как я мог позволить цепочку

(*counter) << "hello" << "test";

Я знаю, что с цепочкой это будет делать это

(*counter).operator<<("hello" << "test");

что явно не имеет никакого смысла, так как есть две строки / символьные массивы
Но я знаю, что есть способ сделать это. Я гуглил это, но каждый вопрос был только о соединении вместе экземпляров одного типа

Затем я попытался вставить два аргумента в функцию и добавить его в список друзей … Я не уверен, но, возможно, мне придется создать новый перегруженный оператор с типом char* или объект потока и сделать его другом A?

Спасибо за помощь, я думаю, должен быть простой ответ, которого я сейчас не вижу.

0

Решение

Вам необходимо вернуть ссылку на *thisпоэтому ваш тип возврата должен быть A&:

A& operator<<(char *str)
{
this->doSomething(str); // as before
return *this;           // return reference to this instance.
}
5

Другие решения

В вашем вопросе есть два неверных предположения, которые я хочу прояснить.

  1. Когда вы хотите позвонить operator<< на указатели, вы должны сделать это
    за каждый звонок, а не только первый. Вот почему

    A *counter = new A();
    (*counter) << "hello";
    

    работает, но

    (*counter) << "hello" << "test";
    

    не делает. Второй operator<< будет вызван на указатель
    возвращается первым, что не то, что вы хотите. Вы должны были написать
    (что некрасиво)

    (*((*counter) << "hello")) << "test";
    
  2. Оператор сдвига может быть соединен в цепочку, а затем оценен слева направо
    правильно, вот почему следующее является еще одним неверным предположением:

    A << "hello" << "test";
    

    Я знаю, что с цепочкой это будет делать это

    A.operator<<("hello" << "test");
    

    Это на самом деле оценивается так:

    A.operator<<("hello").operator<<("test");
    

    что более многословно:

    ( A.operator<<("hello") ).operator<<("test");
    

Цепочка операторов возможна, если объект возвращается operator<< также
инвентарь operator<<чтобы вы могли вернуть копию *this который
имеет тип A, Однако это будет копия объект, который является
не нужно, так как, скорее всего, будет жить только очень
временно и используется только один раз следующим оператором.

Итак, что вы хотите сделать, это вернуть ссылка в operator<<на котором следующий operator<< можно назвать. Это позволяет избежать копирования:

A& operator<<(char *str)
{
this->doSomething(str);
return *this;
}

Возврат указателя возможен, но не приведет к тому, что вы хотите, как описано выше. Синтаксис был бы очень уродливым.

2

operator << должен вернуть ссылку для создания цепочки.

A& operator<<(char *str);

A& A::operator<<(char *str)
{
this->doSomething(str);
return *this;
}

Должен использоваться как

A counter;
counter << "hello" << "test";
1

A *counter = new A();

делает ваш «счетчик» указателем, а не объектом. Чтобы использовать оператор на A, вы можете использовать

(*counter) << "hello"

Кроме того, я бы посоветовал вам еще раз подумать о перегрузке операторов. Хотя поначалу это часто кажется крутой идеей, она может легко привести к коду, который трудно понять и поддерживать.

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector