Помощь - Поиск - Пользователи - Календарь
Полная версия: Перегрузка операторов
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
ammaximus
#include <iostream.h>

class a {
double x;
public:
void operator++(){
this->x = x+9;
return;
};
friend a operator--(a &b){
b.x = b.x-9;
return b;
};
a operator+(a &c){
(this->x)+=(c.x);
return *this;

};
friend a operator-(a &b, a &c){
a temp;
temp.x=(b.x)-(c.x);
return temp;
};

print(){
cout<<x;
cout<<endl;
};

a(){
x=1;
};
};

int main() {
a kot;
kot.print();
++kot;
cout << endl;
kot.print();
--kot;
kot.print();
a rot, mot;
++rot;
mot = kot+rot;
mot.print();


return 1;
}

Просто перегрузка операторов. При этом минусы - друзья, плюсы - функции члены. Я делаю функции встраиваемыми просто для удобства.

В принципе все работает, но функция Принт вызывает warning. Насколько эффективна программа, нет ли каких других неточностей?

Да, вот еще, как реализуется постфиксная запись? Можно ли делать кардинально разные реализации для разных типов вызова операторов?
volvo
Цитата
функция Принт вызывает warning
На более жестком компиляторе это предупреждение тут же становится ошибкой: нельзя описывать функцию без типа возвращаемого значения. Ничего не возвращает - значит void...

Цитата
Да, вот еще, как реализуется постфиксная запись?
Ты имеешь в виду, как реализуется постфиксный инкремент/декремент? Очень просто, в префиксном нет параметров, а в постфиксном в качестве параметра передается int (просто, чтобы отличить одно от другого, так принято делать), то есть, если префиксный был:
void operator++();
// то постфиксный -
void operator ++(int);
// или
friend a operator++(a &b, int);


А вот теперь - касательно ответа на вопрос:
Цитата
Насколько эффективна программа, нет ли каких других неточностей?
А как, прости, ты будешь различать префикс и постфикс, если префиксный вариант ++ у тебя ничего не возвращает? Весь смысл-то и есть в различии, что префикс возвращает измененное значение, а постфикс - НЕизмененное. Сделай вот так, например:
#include <iostream.h>
class a {
friend ostream& operator << (ostream& os, a& obj) {
os << obj.x;
return os;
}

private:
double x;
public:
a& operator++() {
this->x += 9;
return *this;
}
a& operator++(int) {
a& copy = *this;
this->x += 9;
return copy;
}

friend a operator--(a &b) {
b.x = b.x-9;
return b;
}
a operator + (a &c) {
(this->x)+=(c.x);
return *this;
}
friend a operator-(a &b, a &c){
a temp;
temp.x=(b.x)-(c.x);
return temp;
}
void print() {
cout<<x<<endl;
}

a() {
x = 1;
}
};

int main() {
a kot;
// kot.print();
cout << ++kot << endl;
cout << kot << endl;
cout << kot++ << endl;
cout << kot << endl;

// kot.print();
--kot;
kot.print();
a rot, mot;
++rot;
mot = kot+rot;
mot.print();
return 0; // no errors
}
, и поиграйся с этой реализацией, посмотри, на что она способна...
ammaximus
Цитата
нельзя описывать функцию без типа возвращаемого значения.

blink.gif
Вот это я баран... Ошибка из цикла "бабушка и очки"...

Не работает..

a operator++(int) {
a copy = *this;
this->x += 9;
return copy;



По моему, темповская переменная должна быть объектом, а не ссылкой. Но как вернуть ссылку на нее?

a& operator++(int) {
a copy = *this;
this->x += 9;
return & copy; //берем адрес copy


Так че-то не работает.

При возврате функции создается еще одна копия copy, вызывается конструктор и этой копии присваивается значение copy. Я верно мыслю? Так как избежать этого?
volvo
Цитата
Не работает..
А я тебе это и не предлагал... То, что я написал - прекрасно отработало под GCC...
ammaximus
У меня MSV6.
Все ты меня теперь совсем запутал.
a& operator++(int) {//оператор возвращает ссылку на тип а
a& copy = *this; //тут создается ссылочная переменная указывающая на this
this->x += 9; // тут мы меняем this объект
return copy; // тут мы возвращаем ссылку на this


Где ошибка?

MS так все и делает. А что тогда делает ГНУ? Компиляторы разные, но язык один. wacko.gif

a& operator++(int) {//оператор возвращает ссылку на тип а
a copy = *this;
this->x += 9;
return & copy; // берем адрес copy и возвращаем его, поскольку он
// содержит то самое значение которое было ДО


А здесь где ошибка?
volvo
Цитата
А здесь где ошибка?
Ты действительно не видишь разницы между ССЫЛКОЙ и АДРЕСОМ? По какому праву ты хочешь вернуть из метода АДРЕС, когда в заголовке написано, что метод должен возвращать ССЫЛКУ?

Цитата
Где ошибка?
У тебя что, там ошибка? Ни Intel C++, ни GNU, ни Cameau ошибок не видят... По-моему ты сам себя запутал... Если у тебя что-то не компилируется, или не работает - показывай, в какой строке, и что именно происходит... Я компиляторами от MS не пользуюсь, проверить, что там делает MSVC не могу...
ammaximus
Цитата
Ты действительно не видишь разницы между ССЫЛКОЙ и АДРЕСОМ? По какому праву ты хочешь вернуть из метода АДРЕС, когда в заголовке написано, что метод должен возвращать ССЫЛКУ?

Хм...Логично. Честно говоря я постоянно путаю куда поставить амперсанд...
Не суди строго, я учу это вторую неделю. И С я до этого тоже знал в общих чертах(ни черта не знал).

Не ошибка просто участок
cout << ++kot << endl;
cout << kot << endl;
cout << kot++ << endl;
cout << kot << endl;


выводит
10
10
19
19
Хотя должен (я думаю, что должен)
10
10
10
19
Поэтому я начал мудрить. Фраза "Не работает.." не относится к коду под ним, забыл поставить прогал.


Это как раз работает, причем так как я предполагаю, но создает лишнюю копию:
a operator++(int) {
a copy = *this;
this->x += 9;
return copy;



P.S. Извини если туплю.. Это сезонное..
volvo
Хорошо... Что говорит MSVC вот на такой код?
#include <iostream.h>
class a {
friend ostream& operator << (ostream& os, const a& obj) { // Заметь, здесь const !!!
os << obj.x;
return os;
}

private:
double x;
public:
a& operator++() {
this->x += 9;
return *this;
}

a operator++(int) {
a copy(*this);
this->x += 9;
return copy;
}

a() {
x = 1;
}
};
int main() {
a kot;
cout << ++kot << endl;
cout << kot << endl;
cout << kot++ << endl;
cout << kot << endl;

return 0;
}
(это каноническая форма перегрузки пре/пост-фиксного инкремента, взято из книги "C++ Coding Standards" Саттера и Александреску)...

Если при перегрузке операции вывода убрать const, программа тут же перестанет компилироваться... Что теперь выводится?

Кстати, цитата оттуда:
Цитата
In calling code, prefer using the prefix form unless you actually need the original value returned by the postfix version. The prefix form is semantically equivalent, just as much typing, and often slightly more efficient by creating one less object. This is not premature optimization; it is avoiding premature pessimization
ammaximus
Так работает правильно..
Цитата
Если при перегрузке операции вывода убрать const, программа тут же перестанет компилироваться...

Убрал. Ниче не изменилось, снова работает правильно.
volvo
Не должно компилироваться... Ну, понятно, Стандарт языка не для MS... Ладно, закончим флейм на этом...

Так что не волнуйся о создании лишнего экземпляра, оно так и должно быть...
ammaximus
Ок, понятно спасибо smile.gif
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.