Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
#1

Наследование, счетчик, перегрузка операций: К префиксным операциям нет доступа - C++

08.08.2014, 18:20. Просмотров 925. Ответов 22
Метки нет (Все метки)

обычный счетчик с уровнями наследования. почему-то к префиксным операциям нет доступа. в чем дело?


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include "stdafx.h"
#include <iostream>
using namespace std;
///////////////////////////////////////////////////////////
class Counter
{
protected:     // заметьте, что тут не следует использовать private
    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 Postfix : public CountDn
{
public:
    Postfix() : CountDn()
    {}
    Postfix(int c) : CountDn(c)
    {}
    Postfix operator++(int)   
    { 
        return Postfix(count++);
    }
    Postfix operator--(int)           
    { 
        return Postfix(count--);
    }
};
///////////////////////////////////////////////////////////
int main()
{
    Postfix c1;                         // переменные класса CountDn
    Postfix c2(100);
 
    cout << "\nc1 = " << c1.get_count();// выводим значения на экран
    cout << "\nc2 = " << c2.get_count();
 
    ++c1; ++c1; ++c1;                   // увеличиваем c1
    cout << "\nc1 = " << c1.get_count();// показываем результат
 
    --c2; --c2;                         // уменьшаем c2
    cout << "c2 = " << c2.get_count();  // показываем результат
 
    Postfix  c3 = --c2;   // создаем переменную c3 на основе c2
    cout << "\nc3 = " << c3.get_count();// показываем значение
    cout << endl;
 
    return 0;
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.08.2014, 18:20
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Наследование, счетчик, перегрузка операций: К префиксным операциям нет доступа (C++):

Перегрузка оператора << Нет доступа к член данным! В чем загвоздка?
Безумная странная ошибка. Перегрузил оператор вывода потока cout &lt;&lt;. Но в...

Счетчик операций в цикле do-while
Счетчик операций i выдает нереально завышенные цифры: всего 4 преобразования -...

Не работает счетчик операций
Всем доброго вечера,может кто помочь? Изначально было задание переписать...

Нужно вставить счетчик операций в программу
Здравствуйте товарищи программеры тут такая ситуация Есть уже написанная...

Перегрузка операций
Цитата из Р. Лафоре &quot;Объекто-ориентированное программирование в C++&quot;: Далее...

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

22
zss
Модератор
Эксперт С++
6953 / 6515 / 4136
Регистрация: 18.12.2011
Сообщений: 17,202
Завершенные тесты: 1
08.08.2014, 18:53 #2
C++
1
++static_cast<Counter>(c1);
0
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
08.08.2014, 19:13  [ТС] #3
zss, а куда это надо вставить?.. не очень понимаю. не могли бы вы чуть-чуть разъяснить?

Добавлено через 6 минут
куда вставить разобралась уже, но почему так?..

Добавлено через 59 секунд
почему не работают уровни наследования?

Добавлено через 4 минуты
нет, не разобралась таки куда вставить.
0
zss
Модератор
Эксперт С++
6953 / 6515 / 4136
Регистрация: 18.12.2011
Сообщений: 17,202
Завершенные тесты: 1
08.08.2014, 19:24 #4
У Вас
Цитата Сообщение от Pari Посмотреть сообщение
Postfix c1;
...
++c1; ++c1; ++c1;
Т.е. аргумент операции ++ переменная типа Postfix,
а у реализованного оператора - аргумент типа Counter.
Чтобы ее вызвать приводим к нужному типу.
C++
1
2
3
++static_cast<Counter>(c1); 
++static_cast<Counter>(c1); 
++static_cast<Counter>(c1);
0
CyberSolver
101 / 74 / 17
Регистрация: 23.07.2014
Сообщений: 851
Записей в блоге: 1
08.08.2014, 19:29 #5
zss, почему virtual не помогает? Не проще тогда продублировать operator++, чтобы эти убогие касты не писать?
0
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
08.08.2014, 19:33  [ТС] #6
Цитата Сообщение от zss Посмотреть сообщение
Чтобы ее вызвать приводим к нужному типу.
я именно так и написала сначала, но счетчик не сработал

Добавлено через 1 минуту
CyberSolver, смысл задачи просто в том, чтобы ничего не изменять в первых 2 классах
0
zss
Модератор
Эксперт С++
6953 / 6515 / 4136
Регистрация: 18.12.2011
Сообщений: 17,202
Завершенные тесты: 1
08.08.2014, 19:45 #7
Цитата Сообщение от CyberSolver Посмотреть сообщение
почему virtual не помогает
А при чем тут virtual, Вам нужно вызвать метод базового класса.
Еще можно через указатель на базовый класс (тогда приведение не потребуется):
C++
1
2
    Counter* pca=new Postfix;
    ++*pca;
1
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
08.08.2014, 19:54  [ТС] #8
Цитата Сообщение от zss Посмотреть сообщение
Еще можно через указатель на базовый класс (тогда приведение не потребуется)
еще не знаю как пользоваться указателями... можете прямо в коде вставить его куда нужно?
0
zss
Модератор
Эксперт С++
6953 / 6515 / 4136
Регистрация: 18.12.2011
Сообщений: 17,202
Завершенные тесты: 1
08.08.2014, 21:55 #9
Лучший ответ Сообщение было отмечено Pari как решение

Решение

C++
1
2
3
4
5
6
7
int main()
{
    Count* c1=new Postfix;
    cout << "\nc1 = " << c1->get_count();// выводим значения на экран
    ++*c1; ++*c1; ++*c1;                   // увеличиваем c1
    cout << "\nc1 = " << c1->get_count();// показываем результат
...
0
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
09.08.2014, 19:32  [ТС] #10
Цитата Сообщение от zss Посмотреть сообщение
Count*
компилятор выдает ошибку, Сount не определен
0
zss
Модератор
Эксперт С++
6953 / 6515 / 4136
Регистрация: 18.12.2011
Сообщений: 17,202
Завершенные тесты: 1
09.08.2014, 19:44 #11
Ну уж на свой Counter исправить можно и самостоятельно!
1
Alex5
1120 / 781 / 231
Регистрация: 12.04.2010
Сообщений: 2,007
09.08.2014, 21:57 #12
Цитата Сообщение от Pari Посмотреть сообщение
почему-то к префиксным операциям нет доступа. в чем дело?
Можно так написать:
C++
1
2
    Postfix c1;
    c1.Counter::operator++();
1
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
09.08.2014, 22:08  [ТС] #13
да, эти способы работают, спасибо, но я не могу понять, почему все так усложняется... почему наследование классов не работает прямо?
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
09.08.2014, 22:58 #14
Лучший ответ Сообщение было отмечено Pari как решение

Решение

Цитата Сообщение от Pari Посмотреть сообщение
но я не могу понять, почему все так усложняется... почему наследование классов не работает прямо?
Потому что происходит сокрытие имени. Аналогично с обычными функциями:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class A
{
public:
    void foo(int) {}
};
 
class B : public A
{
public:
    void foo() {}
};
 
int main()
{
    B b;
 
    b.foo(2); //ошибка, foo без параметров скрыла функцию из базового класса
}
Чтобы это побороть нужно добавить функцию в текущую область видимости:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class A
{
public:
    void foo(int) {}
};
 
class B : public A
{
public:
    using A::foo; //тут
    void foo() {}
};
 
int main()
{
    B b;
 
    b.foo(2); //работает
}
Аналогично нужно исправить первоначальный пример:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using namespace std;
///////////////////////////////////////////////////////////
class Counter
{
protected:     // заметьте, что тут не следует использовать private
    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 Postfix : public CountDn
{
public:
    Postfix() : CountDn()
    {}
    Postfix(int c) : CountDn(c)
    {}
    Postfix(CountDn const &dn) : CountDn(dn)
    {}
 
    using Counter::operator++;
    using CountDn::operator--;
 
    Postfix operator++(int)
    {
        return Postfix(count++);
    }
    Postfix operator--(int)
    {
        return Postfix(count--);
    }
};
///////////////////////////////////////////////////////////
int main()
{
    Postfix c1;                         // переменные класса CountDn
    Postfix c2(100);
 
    cout << "\nc1 = " << c1.get_count();// выводим значения на экран
    cout << "\nc2 = " << c2.get_count();
 
    ++c1; ++c1; ++c1;                   // увеличиваем c1
    cout << "\nc1 = " << c1.get_count();// показываем результат
 
    --c2; --c2;                         // уменьшаем c2
    cout << "c2 = " << c2.get_count();  // показываем результат
 
    Postfix  c3 = --c2;   // создаем переменную c3 на основе c2
    cout << "\nc3 = " << c3.get_count();// показываем значение
    cout << endl;
 
    return 0;
}


Добавлено через 4 минуты
почему наследование классов не работает прямо?
Строго говоря, наследование тут не при чем вообще. Это общий принцип замещения имен в зависимости от области видимости.
C++
1
2
3
4
5
6
7
8
9
int a = 0;
 
int main()
{
    int a = 2;
 
    printf("%d", a); // выведет 2, локальная "а" скрыла глобальную
    printf("%d", ::a); //выведет 0
}
1
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
10.08.2014, 02:04  [ТС] #15
DrOffset, спасибо вам огромное за очень подробное и полезное разъяснение! я наконец все поняла!)
1
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
10.08.2014, 02:19 #16
Pari, не за что.
Так что не надо писать ни касты, ни дубликаты функций, ни еще что-то такое - это все шаманство.
Всегда, если что-то не понятно, нужно искать истинные причины, а не сомнительные обходные маневры. Говоря проще, "зрите в корень", поэтому за вот этот вопрос
Цитата Сообщение от Pari Посмотреть сообщение
спасибо, но я не могу понять, почему все так усложняется... почему наследование классов не работает прямо?
плюс поставлю.
Успехов.
0
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
10.08.2014, 02:24  [ТС] #17
DrOffset, еще раз спасибо и еще один маленький вопрос, чтобы окончательно прояснить ситуацию:
в классе Postfix для чего нужен третий конструктор? спросить, увы, не у кого совершенно, все по учебнику учу(
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
10.08.2014, 02:42 #18
Цитата Сообщение от Pari Посмотреть сообщение
в классе Postfix для чего нужен третий конструктор?
мы "испортировали" оператор-- из базового класса CountDn. В строке 71 есть вот такой код
C++
1
Postfix  c3 = --c2;   // создаем переменную c3 на основе c2
operator-- возвращает объект класса CountDn. Но инициализация требуется объекта с3 класса Postfix. В классе Postfix нет способа провести такую инициализацию, поэтому нужно было написать конструктор, чтобы добавить возможность это делать.

Добавлено через 10 минут
Pari, кстати префиксные операторы реализованы не совсем корректно. Правильнее будет так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Counter
{
protected: 
    unsigned int count;              // счетчик
public:
    Counter() : count(0)              // конструктор без параметров
    { }
    Counter(int c) : count(c)        // конструктор с одним параметром
    { }
    unsigned int get_count() const   // получение значения
    {
        return count;
    }
    Counter & operator++()             // оператор увеличения
    { 
        ++count;
        return *this;
    }
};
class CountDn : public Counter
{
public:
    CountDn() : Counter()            // конструктор без параметров
    { }
    CountDn(int c) : Counter(c)      // конструктор с одним параметром
    { }
    CountDn & operator--()             // оператор уменьшения
    { 
        --count;
        return *this;
    }
};
1
Pari
40 / 3 / 6
Регистрация: 24.11.2013
Сообщений: 139
10.08.2014, 02:47  [ТС] #19
Цитата Сообщение от DrOffset Посмотреть сообщение
Правильнее будет так:
это вы кажется указатели использовали? если да, то я еще до них не дошла, как раз следующая глава изучаемой мною книги о них.
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
10.08.2014, 02:55 #20
Цитата Сообщение от Pari Посмотреть сообщение
это вы кажется указатели использовали?
Это ссылки. Можно сказать, более ограниченная (и соответственно безопасная) версия указателя. Но формально ссылка - это не указатель. Это скорее псевдоним для существующего объекта. Хотя во многих ситуациях ее внутренняя реализация будет идентична указателю (т.е. компилятором будут сгенерированы идентичные асссемблерные инструкции).
Цитата Сообщение от Pari Посмотреть сообщение
если да, то я еще до них не дошла, как раз следующая глава изучаемой мною книги о них.
Ну торопиться я не заставлю же. Как разберешь нужную тему, можно вернуться к этому примеру
0
10.08.2014, 02:55
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.08.2014, 02:55
Привет! Вот еще темы с решениями:

Перегрузка операций
Всем привет, нужно помощь, я самостоятельно изучаю программирование, наткнулся...

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

ПЕРЕГРУЗКА ОПЕРАЦИЙ
Не знаю как делать задания( Прошу помощи 1) Ввести класс для работы с...

Перегрузка операций
Всем привет! Помогите пожалуйста с перегрузкой операций. У меня есть вот 4-ая...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru