Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> C++ Error C2675, не могу исправить ошибку 
:(
    Опции темы
Capella
Дата 19.7.2008, 08:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



В С++ я новичок. Читаю Роберта Лафоре "ООП в С++" и выполняю упражнения. В главе 9 "Наследование" упражнении 7 сказано использовать листинг из начала главы и добавить возможность префиксного инкременирования и декреминирования используя наследование.

Код

#include <iostream>

using namespace std;

class Counter //класс из листинга
{
    protected:
        unsigned int count;
    public:
        Counter(): count(0)
        {}
        Counter(int c): count(с)
        {}
        unsigned int get_count()const
        {return count;}
        Counter operator++ ()
        {return Counter(++count);}
};

class CountDn : public Counter //класс из листинга
{
    public:
        Counter operator-- ()
        {return Counter(--count);}
};

class Countpost : public CountDn //мой класс
{
    public:
        Counter operator++ (int)
        {return Counter(count++);}
        Counter operator-- (int)
        {return Counter(count--);}
};

int main()
{
    Countpost c1;
    CountDn c2;

    ++c2;//ошибки нет, так как используется оператор родителя
    cout << "\n c1=" << c1.get_count();
    c1++; c1++; c1++;
    cout << "\n c1=" << c1.get_count();
    ++c1; //ошибка. Аналогично если --с1
    c1--;
    cout << "\n c1=" << c1.get_count();
    cout << endl;
    system("Pause");
    return 0;
}


сообщение Visual Studia 2008 об ошибке (в случае с "++с1;"):
error C2675: unary '++' : 'Countpost' does not define this operator or a conversion to a type acceptable to the predefined operator

Помогите решить проблему пожалуйста)))

Это сообщение отредактировал(а) Capella - 19.7.2008, 11:40
PM MAIL   Вверх
Annihilator
Дата 19.7.2008, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Ты перегрузил только для постфиксного инкремента/декремента, а используешь еще и префиксный, значит нужно и для него определить опрерации
Код

Counter operator++ ()
{
    count++;
    return *this;
}
Counter operator-- ()
{
    count--;
    return *this;
}

 Практикуй отступы - код читать невозможно!
Используй кнопку "КОД", она №5 над окошком для отправки сообщения

Это сообщение отредактировал(а) Annihilator - 19.7.2008, 09:21


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
Capella
Дата 19.7.2008, 11:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



Это же наследование. Если я буду перегружать каждую операцию, то смысла в нём нет. Просто заново класс написать и всё.
Плюс если создать экземпляр класса CountDn и применить к нему операцию инременирования описанную в родителе, то ошибки не будет, что в листинге отражено:

CountDn c2;

++c2;

P.S. Сорри за отступы)))

PM MAIL   Вверх
Annihilator
Дата 19.7.2008, 11:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



Ты в своем примере перегрузил только для постфиксного оператора (с++), но используешь-то ты еще и префиксный (++с), а это разные вещи, разные механизмы. Почитай чем отличаются. Ты должен дополнить свой код перегрузкой префиксной формы, иначе компилятор не врубится, что ты от него хочешь!
ИМХО Лафоре - далеко не лучшая книга для новичков, как-то там все непоследовательно. Возьми лучше "Шилдт - С++ Базовый курс", сразу въедешь!
Код

count©

криво распознал  smile надо писать count(с)

Это сообщение отредактировал(а) Annihilator - 19.7.2008, 11:21


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
Capella
Дата 19.7.2008, 11:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



Смотри внимательно. Префиксное инременирование перегружено в самом первом классе, который является родителем CountDn, в котором перегружен префиксный декремент. Ну а мой класс Countpost перегружает оставшиеся операторы постфиксного инкременирования и декременирования. Так как мой класс наследник CounDn, который в свою очередь наследник класса Counter, то он (мой класс) должен был унаследовать префиксные операторы.

P.S. Чем отличаются я знаю))) . И кстати компилятор использует операцию постфиксную вместо префиксной, если не нашёл таковую. И наоброт. Проверено...
Вот док-во:
 warning C4620: no postfix form of 'operator ++' found for type 'CountDn', using prefix form
Я не много изменил код, чтобы показать это. В том коде, который я представил тут, данного ворнинга нету.

Это сообщение отредактировал(а) Capella - 19.7.2008, 11:42
PM MAIL   Вверх
IKM2007
Дата 19.7.2008, 12:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зима близко
**


Профиль
Группа: Участник
Сообщений: 702
Регистрация: 26.4.2008
Где: olmedreca

Репутация: 3
Всего: 40



Цитата(Capella @  19.7.2008,  11:35 Найти цитируемый пост)
 И кстати компилятор использует операцию постфиксную вместо префиксной, если не нашёл таковую.

Если обьявлена только префиксная операция, то компилятор использует ее и как поствиксную, но если обьявлена только поствиксная операция, то она используется только как поствиксная.

Это сообщение отредактировал(а) IKM2007 - 19.7.2008, 12:19


--------------------
"К чёрту обстоятельства, я создаю возможности."
Брюс Ли
PM MAIL Skype   Вверх
Capella
Дата 19.7.2008, 12:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



Вообще-то я это и написал. Только проблема в том, что у меня ВСЁ объявлено, а использует он только свои операторы. Хотя экземпляр класса CountDn  с успехом использует как свой оператор, так и оператор родителя.

PM MAIL   Вверх
IKM2007
Дата 19.7.2008, 13:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зима близко
**


Профиль
Группа: Участник
Сообщений: 702
Регистрация: 26.4.2008
Где: olmedreca

Репутация: 3
Всего: 40



Вот сама проблема.

Код

class C1 //базовый
{
    protected:
        int count;
    public:
        ...
         C1 operator++ ()//префикс
        {return C1(++count);}
        
};
class C2 : public C1 //производной
{public:
       
C1 operator++ (int)//постфикс
        {return C1(count++);}
};
void main()
{
    C2 а;
    ++а; //ошибка.
}

но если постфикс написать в базовом классе, а префикс в производном, то сработает.Сам не знаю, почему так.


--------------------
"К чёрту обстоятельства, я создаю возможности."
Брюс Ли
PM MAIL Skype   Вверх
Capella
Дата 19.7.2008, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



попробуй теперь 3 класс от второго сделать... и его экземпляром вызвать операторы. Не получается. В том-то и дело что пример с 2 классами базовым и наследником работает. А вот пример с базовым, наследником и наследником наследника нет...
PM MAIL   Вверх
IKM2007
Дата 19.7.2008, 14:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Зима близко
**


Профиль
Группа: Участник
Сообщений: 702
Регистрация: 26.4.2008
Где: olmedreca

Репутация: 3
Всего: 40



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

Это сообщение отредактировал(а) IKM2007 - 19.7.2008, 14:05


--------------------
"К чёрту обстоятельства, я создаю возможности."
Брюс Ли
PM MAIL Skype   Вверх
Capella
Дата 19.7.2008, 15:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



и правда странно. 
P.S. Главный вопрос открыт. Почему не работает, так как показано в самом начале?
PM MAIL   Вверх
Annihilator
Дата 19.7.2008, 19:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


bytegrinder
**


Профиль
Группа: Участник
Сообщений: 493
Регистрация: 21.11.2006
Где: Омск

Репутация: 1
Всего: 3



вот так надо
Код

class C1 {
protected:
    int count;
public:
    C1(): count(0){}
    C1(int c): count©{}
    C1 operator++() // prefix form 
    {
        return C1(++count);
    }
};
class C2 : public C1 {
public:
    C1::operator++;
    C1 operator++(int q) // postfix form
    {
        return C1(count++);
    }
};
void main()
{
    C1 b(3);
    C2 a;
    a++;
    ++a;
}

Всем кому интересно, читаем здесь
А конкретно для этого примера, цитирую

Цитата

Ambiguous base classes (C++ only)

When you derive classes, ambiguities can result if base and derived classes have members with the same names. Access to a base class member is ambiguous if you use a name or qualified name that does not refer to a unique function or object. The declaration of a member with an ambiguous name in a derived class is not an error. The ambiguity is only flagged as an error if you use the ambiguous member name.

For example, suppose that two classes named A and B both have a member named x, and a class named C inherits from both A and B. An attempt to access x from class C would be ambiguous. You can resolve ambiguity by qualifying a member with its class name using the scope resolution (:smile operator.


Код

class B1 {
public:
  int i;
  int j;
  void g(int) { }
};

class B2 {
public:
  int j;
  void g() { }
};

class D : public B1, public B2 {
public:
  int i;
};

int main() {
  D dobj;
  D *dptr = &dobj;
  dptr->i = 5;
//  dptr->j = 10;
  dptr->B1::j = 10;
//  dobj.g();
  dobj.B2::g();
}


Цитата

The statement dptr->j = 10 is ambiguous because the name j appears both in B1 and B2. The statement dobj.g() is ambiguous because the name g appears both in B1 and B2, even though B1::g(int) and B2::g() have different parameters.

The compiler checks for ambiguities at compile time. Because ambiguity checking occurs before access control or type checking, ambiguities may result even if only one of several members with the same name is accessible from the derived class.


Это сообщение отредактировал(а) Annihilator - 19.7.2008, 20:33


--------------------
Если вы не можете сделать хоpошyю пpогpаммy, сделайте, чтобы она по кpайней меpе выглядела хоpошо
PM ICQ   Вверх
Capella
Дата 20.7.2008, 06:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 7
Регистрация: 19.7.2008

Репутация: нет
Всего: нет



Спасибо огромное smile 
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0517 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.