Я борюсь с перегрузкой оператора, так как хочу, чтобы он позволял цепочку
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
?
Спасибо за помощь, я думаю, должен быть простой ответ, которого я сейчас не вижу.
Вам необходимо вернуть ссылку на *this
поэтому ваш тип возврата должен быть A&
:
A& operator<<(char *str)
{
this->doSomething(str); // as before
return *this; // return reference to this instance.
}
В вашем вопросе есть два неверных предположения, которые я хочу прояснить.
Когда вы хотите позвонить operator<<
на указатели, вы должны сделать это
за каждый звонок, а не только первый. Вот почему
A *counter = new A();
(*counter) << "hello";
работает, но
(*counter) << "hello" << "test";
не делает. Второй operator<<
будет вызван на указатель
возвращается первым, что не то, что вы хотите. Вы должны были написать
(что некрасиво)
(*((*counter) << "hello")) << "test";
Оператор сдвига может быть соединен в цепочку, а затем оценен слева направо
правильно, вот почему следующее является еще одним неверным предположением:
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;
}
Возврат указателя возможен, но не приведет к тому, что вы хотите, как описано выше. Синтаксис был бы очень уродливым.
operator <<
должен вернуть ссылку для создания цепочки.
A& operator<<(char *str);
A& A::operator<<(char *str)
{
this->doSomething(str);
return *this;
}
Должен использоваться как
A counter;
counter << "hello" << "test";
A *counter = new A();
делает ваш «счетчик» указателем, а не объектом. Чтобы использовать оператор на A, вы можете использовать
(*counter) << "hello"
Кроме того, я бы посоветовал вам еще раз подумать о перегрузке операторов. Хотя поначалу это часто кажется крутой идеей, она может легко привести к коду, который трудно понять и поддерживать.