2013-07-22 3 views
0

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

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

Ваш оператор будет лучше принимать 'const char *'. –

ответ

5

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

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

Ну, вы * можете * вернуть по значению и цепочки звонки просто отлично. Но вы можете объяснить, почему вы обычно * хотите * возвращаться по ссылке. – jrok

+0

отлично, отлично работает и имеет смысл – raemaerne

1

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

A& operator<<(char *str); 

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

должны использоваться как

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

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

(*counter) << "hello" 

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

+0

'(* A) <<" привет "' должен быть '(* counter) <<" hello "'. – ForEveR

+0

А ты прав. Я изменю его в своем сообщении – raemaerne

+0

К сожалению, ForEveR прав, я обновлю свой ответ. – ecotax

2

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

  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; 
} 

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

+0

+1 - хорошее объяснение. Re "Когда вы хотите вызвать' operator << 'на указатели, вы должны сделать это для каждого вызова, а не только для первого." - это верно, когда 'operator <<' является членом, но не членский оператор T * << (T *, const char *) 'также можно представить, если причудливо .... –

+0

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

Смежные вопросы