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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема при наследовании. 
:(
    Опции темы
halfnode
Дата 28.1.2011, 04:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всем доброго времени суток!
Никак не могу разобраться в следующем вопросе, который касается наследования.
Если брать наследование просто от родительского класса, то там проблем не возникает.
То же самое, если новый класс является производным от двух независимых классов.
Но никак не могу сообразить, что делать, если производный класс будет являться уже третьей ступенью?
Т.е. от базового класса А, создается производный класс Б, который дополняет класс А некоторыми допвозможностями.
И тут меня просят, без изменения классов А и Б, применяя наследование, создать класс В, который будет, опять таки, увеличивать функциональность классов А и производного от него Б. 
Вообще, Лафоре очень доступно излагает свои мысли. Но, видимо, что-то у меня переклинило. Никак не получается решить вот такую вот задачу:
"Используя наследование, добавьте возможность использования постфиксных операций для случаев увеличения и уменьшения."
Counter - базовый класс, где реализована возможность префиксного инкремента.
CountDn - производный от Counter, с добавкой префиксного декремента.
CountM - моя жалкая попытка реализовать класс, который бы добавлял возможность постфиксных операций.

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

Очень прошу, для дурака объясните, как вообще происходит наследование, если это уже третий класс и ему нужно дополнить возможности первых двух?

Заранее спасибо.

Код

class Counter
{
protected:
        unsigned int count;
public:
        Counter(): count(0)
        {}
        Counter (int c): count(c)
        {}
        unsigned int get_count() const
        {return count;}
        Counter operator++ ()
        {return Counter(++count);}
};
 
class CountDn : public Counter
{
public:
        CountDn() : Counter()
        {}
        CountDn(int c) : Counter(c)
        {}
        CountDn operator--()
        {return CountDn(--count);}
};
 
class CountM : public Counter, public  CountDn
{
public:
        CountM () : CountDn() //конструктор от этого класса, т.к. по идее, он все-равно доберется до класса Counter
        {}
        CountM(int g) : CountDn (g)
        {}
        CountM operator++(int)
        {return CountM(CountDn::count++);}  // без прямого указания, ругается на то, что count не является однозначным
        CountM operator--(int)
        {return CountM(CountDn::count--);}
};
 
int main()
{
  
   CountM cm1;
   cm1++;  //пройдет
   ++сm1;  //ошибка
   return 0;
}



Это сообщение отредактировал(а) halfnode - 28.1.2011, 04:26
PM MAIL   Вверх
azesmcar
Дата 28.1.2011, 07:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



halfnode, 

Цитата(halfnode @  28.1.2011,  04:15 Найти цитируемый пост)
class CountM : public Counter, public  CountDn

Вот ошибка.
Класс CountDn уже наследует класс Counter, наследовать от Counter снова не надо.
Наследование идет так
Класс A -> Класс B -> Класс C
В данном случае Класс C будет включать в себя класс B, который включает класс A.

В общем вот компилирующийся код, но он все равно далек от идеала. Например префиксный оператор ++ должен возвращать ссылку. В твоем случае если не переписать его в наследнике, то он будет возвращать не CountM а Counter (так он определен в классе Counter).
Код

class Counter
{
protected:
    unsigned int count;
public:
    Counter(): count(0)
    {}
    Counter (int c): count(c)
    {}
    unsigned int get_count() const
    {return count;}
    Counter operator++ ()
    {return Counter(++count);}
};

class CountDn : public Counter
{
public:
    CountDn() : Counter()
    {}
    CountDn(int c) : Counter(c)
    {}
    CountDn operator--()
    {return CountDn(--count);}
};

class CountM : public  CountDn
{
public:
    CountM () : CountDn()
    {}
    CountM(int g) : CountDn (g)
    {}
    CountM operator++(int)
    {return CountM(CountDn::count++);}
    CountM operator--(int)
    {return CountM(CountDn::count--);}

    using Counter::operator++;
};

int main()
{

    CountM cm1;
    cm1++;
    ++cm1;
    return 0;
}


Это сообщение отредактировал(а) azesmcar - 28.1.2011, 07:59
PM   Вверх
halfnode
Дата 28.1.2011, 12:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Спасибо azesmcar!
Но тут много НО. smile
Во-первых - использование using, такого еще не было нигде в книге. Но в среднем, я понял для чего. Чтобы не писать большущее обращение к оператору из main.
Во-вторых - префиксный декремент до сих пор, негодяй такой, не хочет работать.


п.с. Первый вариант именно таким и был. Тут все логично как-то сразу. Единственное, что у меня не было строки using Counter::operator++.


UPD: Прописал using CountDn::operator--. Все вроде как заработало.

Это сообщение отредактировал(а) halfnode - 28.1.2011, 12:20
PM MAIL   Вверх
azesmcar
Дата 28.1.2011, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


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

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



Цитата(halfnode @  28.1.2011,  12:18 Найти цитируемый пост)
Во-вторых - префиксный декремент до сих пор, негодяй такой, не хочет работать.

Да, у тебя там имя переменной кажется кирилицей написано smile 

Удали и напиши заново.
PM   Вверх
mes
Дата 28.1.2011, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(halfnode @  28.1.2011,  11:18 Найти цитируемый пост)
Чтобы не писать большущее обращение к оператору из main.

не совсем так.. из за того что в противном случае определение оператора в наследнике перекроет видимость оператора предка.. 
а так using указывает компилятору, что он (оператор предка) участвуют в перегрузке наряду с новоопределенными операторами.. 

P.S. для функций было бы то же самое


--------------------
PM MAIL WWW   Вверх
halfnode
Дата 28.1.2011, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



ага, с using разобрался, спасибо. Это очень ценная штука.
Но почему не хочет работать перегруженный уже в производном классе CounterDn, operator--() ?
Т.е. пока я рядом с using Counter::operator++; не прописал using CountDn::operator--;, обращение из main вида --cm1 - выкидывало ошибку!
п.с. имя объекта введено латиницей, точно. smile
Вообще странно, ведь CountM это производный CountDn, и он должен был в первую очередь наследовать перегруженный --. Непонятно. 
В других задачах, с наследованием A->B->C, таких проблем ни разу не встречал. А тут прям одни вопросы.

UPD: Надо полагать, что с изучением указателей, большинство таких проблем как-то нивелируется. Надеюсь, по крайней мере. smile Но указатели, это только следующая глава, увы.

Это сообщение отредактировал(а) halfnode - 28.1.2011, 16:32
PM MAIL   Вверх
mes
Дата 28.1.2011, 16:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(halfnode @  28.1.2011,  15:30 Найти цитируемый пост)
Но почему не хочет работать перегруженный уже в производном классе CounterDn, operator--() ?
Т.е. пока я рядом с using Counter::operator++; не прописал using CountDn::operator--;, обращение из main вида --cm1 - выкидывало ошибку!
п.с. имя объекта введено латиницей, точно. 
Вообще странно, ведь CountM это производный CountDn, и он должен был в первую очередь наследовать перегруженный --. Непонятно. 

 smile 
так и не понял, заработал он в конце концов или нет.. если до сих пор не работает, то ошибку в студию.. 



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


Новичок



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

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



Если не добавлять using CountDn::operator--; то при попытке в main вызвать --cm1 выпадает следующее:
Код

error C2675: унарный "--": "CountM" не определяет этот оператор или преобразование к типу приемлемо к встроенному оператору


PM MAIL   Вверх
mes
Дата 28.1.2011, 18:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(halfnode @  28.1.2011,  16:45 Найти цитируемый пост)
Если не добавлять using CountDn::operator--; 

ну так написано же было  выше :
Цитата(mes @  28.1.2011,  14:43 Найти цитируемый пост)
в противном случае определение оператора в наследнике перекроет видимость оператора предка.. 




--------------------
PM MAIL WWW   Вверх
halfnode
Дата 28.1.2011, 21:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Наследник,  CountM имеет только постфиксные перегрузки. А его предок CountDn, как раз таки префиксный декремент.
В случае с Counter, понятно. Перекроет. Но как постфиксная перегрузка может перекрыть префиксную перегрузку предка?

Это сообщение отредактировал(а) halfnode - 28.1.2011, 21:17
PM MAIL   Вверх
mes
Дата 28.1.2011, 22:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


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

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



Цитата(halfnode @  28.1.2011,  20:16 Найти цитируемый пост)
. Но как постфиксная перегрузка может перекрыть префиксную перегрузку предка?

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



--------------------
PM MAIL WWW   Вверх
halfnode
Дата 29.1.2011, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



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

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

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

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

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


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

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


 




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


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

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