Форум программистов, компьютерный форум CyberForum.ru

Наследование и перегрузка методов - C++

Восстановить пароль Регистрация
 
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
09.08.2012, 14:31     Наследование и перегрузка методов #1
Здравствуйте. Пытаюсь выполнить упр. 8 из главы 11 книги Р.Лафоре "ООП в С++", соорудил такое древо классов (картинка в конце поста). Если коротко, то я пыжился сотворить стек, который сможет принимать как символы, так и веществ. числа. Ничего лучше не придумал, как наследовать два класса. Вот выжимка из реализующего кода (За извращенца прошу меня не считать - я только начал изучать С++)

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
#include <iostream>
 
using namespace std;
////////////////////////////////////////////////////////////////////////////////
class Symbol
{
    protected :
        int sizeOf;
 
    public :
        Symbol(int size) : sizeOf (size)
        {/* empty */}
        virtual ~Symbol()
        {/* empty */}
};
////////////////////////////////////////////////////////////////////////////////
class Operator : virtual public Symbol
{
    protected :
        char *stack;
 
    public :
        Operator(int size) : Symbol(size)
        { /* ... */ }
        void push(char sym)
        { /* ... */ }
        char pop(void)
        { return '0';}
};
////////////////////////////////////////////////////////////////////////////////
class Number : virtual public Symbol
{
    protected :
        float *stack;
 
    public :
        Number(int size) : Symbol(size)
        { /* ... */ }
        void push(float num)
        { /* ... */ }
        float pop(void)
        { return 0.0f; }
};
////////////////////////////////////////////////////////////////////////////////
class Stack : public Operator, public Number
{
    public :
        Stack(int size) : Symbol(size), Operator(size), Number(size)
        {/* empty */}
};
////////////////////////////////////////////////////////////////////////////////
int main()
{
    Stack* stackPtr = new Stack(100); // error: request for member 'push' is ambiguous
 
    // Очень хотелось бы делать так:
    stackPtr->push('+');
    stackPtr->push(100);
 
    cout << endl;
    return 0;
}
И вот в конце, когда я пытаюсь создать объект производного класса, компилятор ругается на неоднозначность: error: request for member 'push' is ambiguous -я указал в листинге, где имено. Но позвольте, какая же неоднозначность? А как же разные типы данных в сигнатурах методов "push": Operator :: push(char), другой Number :: push(float), и я так подозреваю что с методами "pop" будет та же проблема (только там возвращаемые значения отличаются). Почему так - объясните пожалуйста новичку.

В UML я тоже не особо силён, но надеюсь схема понятна:
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
09.08.2012, 14:31     Наследование и перегрузка методов
Посмотрите здесь:

Наследование и перегрузка << C++
Перегрузка методов и преобразование типов. C++
C++ Наследование, и перегрузки методов
C++ Перегрузка методов
Наследование классов. Конфликт методов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
09.08.2012, 14:33  [ТС]     Наследование и перегрузка методов #2
Наследование и перегрузка методов
John Prick
754 / 687 / 123
Регистрация: 27.07.2012
Сообщений: 1,974
Завершенные тесты: 3
09.08.2012, 14:41     Наследование и перегрузка методов #3
Неоднозначность. Будет работать, если конкретно указать, какой именно push вызывается:
C++
1
2
    stackPtr->Operator::push('+');
    stackPtr->Number::push(100);
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
09.08.2012, 15:31  [ТС]     Наследование и перегрузка методов #4
Да John Prick спасибо, что напомнили про уточнения. А не подскажете, как всё - таки построить иерархию классов или что то ещё, что бы была возможность вызывать методы именно так:

C++
1
2
stackPtr->push('+');
stackPtr->push(100);
И есть ли в С++ вообще такая возможность?
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
09.08.2012, 15:37     Наследование и перегрузка методов #5
Цитата Сообщение от moskitos80 Посмотреть сообщение
Если коротко, то я пыжился сотворить стек, который сможет принимать как символы, так и веществ. числа. Ничего лучше не придумал, как наследовать два класса.
Наследование стека от символов вам ничего не даст, нужно исходить из того что стек - это контейнер - он содержит данные, а по-вашему стек является числом и оператором. Стек должен содержать массив указателей на базовый класс Symbol
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
#include <iostream>
 
class Symbol
{
//...
};
 
class Operator : public Symbol
{
//...
};
 
class Number : public Symbol
{
//...
};
 
class Stack 
{
public:
//...
    void push(char c)
    {
        m_arr[++m_size] = new Operator(c);
    }
 
    void push(float c)
    {
        m_arr[++m_size] = new Number(c);
    }
private:
    Symbol*     m_arr;
    std::size_t m_size;
};
 
int main()
{
    Stack stack;
 
    stack.push('+');
    stack.push(100.0f);
 
    return 0;
}
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
09.08.2012, 18:40  [ТС]     Наследование и перегрузка методов #6
ЗдОрово! Спасибо Jupiter А я не догадался так сделать Я вот уже зачем то и агрегацию приплёл... скажите в таком способе много недостатков:

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
 
using namespace std;
 
////////////////////////////////////////////////////////////////////////////////
class CharStack
{
    protected :
        char *stack;
        int  sizeOf;
        int current;
 
    public :
        CharStack(int size) : sizeOf(size)
        {
            this->stack = new char [this->sizeOf];
        }
        ~CharStack()
        {
            delete [] this->stack;
        }
        void push(char ch)
        {
            this->stack[this->current++] = ch;
        }
        char pop(void)
        {
            return this->stack[--this->current];
        }
};
////////////////////////////////////////////////////////////////////////////////
class FloatStack
{
    protected :
        float *stack;
        int   sizeOf;
        int  current;
 
    public :
        FloatStack(int size) : sizeOf(size)
        {
            this->stack = new float [this->sizeOf];
        }
        ~FloatStack()
        {
            delete [] this->stack;
        }
        void push(float fl)
        {
            this->stack[this->current++] = fl;
        }
        float pop(void)
        {
            return this->stack[--this->current];
        }
};
////////////////////////////////////////////////////////////////////////////////
class Stack
{
    protected :
        int sizeOf;
        CharStack* chPtr;
        FloatStack* flPtr;
 
    public :
        Stack(int size) : sizeOf(0)
        {
            this->flPtr = new FloatStack(size);
            this->chPtr = new CharStack(size);
        }
        ~Stack()
        {
            delete this->flPtr;
            delete this->chPtr;
        }
        // äëÿ char
        void push(char ch)
        {
            this->sizeOf++;
            this->chPtr->push(ch);
        }
        char chPop(void)
        {
            this->sizeOf--;
            return this->chPtr->pop();
        }
        // äëÿ float
        void push(float fl)
        {
            this->sizeOf++;
            this->flPtr->push(fl);
        }
        float flPop(void)
        {
            this->sizeOf--;
            return this->flPtr->pop();
        }
 
        int getSize(void)
        {
            return this->sizeOf;
        }
};
////////////////////////////////////////////////////////////////////////////////
 
int main()
{
    Stack* stackPtr = new Stack(100);
 
    // LIFO
    stackPtr->push(50.5f);// 4
    stackPtr->push('+');  // 3
    stackPtr->push(100.f);// 2
    stackPtr->push('*');  // 1
    stackPtr->push(2.5f); // 0
 
    while (stackPtr->getSize()) {
        // Г—ВёГІГ*. ГЅГІГ® îïåðГ*òîðû, Г*ГҐ Г·ВёГІГ*. - ГЅГІГ® îïåðГ*Г*äû
        if (!(stackPtr->getSize() % 2)) {
            cout << "Operator " << stackPtr->chPop() << endl;
        } else {
            cout << "Operand  " << stackPtr->flPop() << endl;
        }
    }
 
    delete stackPtr;
 
    cout << endl;
    return 0;
}
Вот схема:
Наследование и перегрузка методов
Jupiter
Каратель
Эксперт C++
6542 / 3962 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
09.08.2012, 18:49     Наследование и перегрузка методов #7
Цитата Сообщение от moskitos80 Посмотреть сообщение
Я вот уже зачем то и агрегацию приплёл...
так тоже пойдет, только агрегировать можно и сами объекты стеков, а не указатели на них
C++
1
2
3
4
5
6
7
class Stack
{
private:
    int sizeOf;
    CharStack chPtr;
    FloatStack flPtr;
//...
не стоит злоупотреблять оператором new, тем более что особой неоходимости в нем нет
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.08.2012, 18:55     Наследование и перегрузка методов
Еще ссылки по теме:

C++ Перегрузка методов класса
C++ Перегрузка методов класса Прямоугольник
Наследование параметризованных методов C++

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

Или воспользуйтесь поиском по форуму:
moskitos80
 Аватар для moskitos80
39 / 39 / 0
Регистрация: 04.10.2011
Сообщений: 128
09.08.2012, 18:55  [ТС]     Наследование и перегрузка методов #8
Цитата Сообщение от Jupiter Посмотреть сообщение
не стоит злоупотреблять оператором new, тем более что особой неоходимости в нем нет
Премного благодарен за совет, надеюсь понимание, когда нужно выделять память, а когда можно обойтись - придёт со временем.
Yandex
Объявления
09.08.2012, 18:55     Наследование и перегрузка методов
Ответ Создать тему
Опции темы

Текущее время: 07:53. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru