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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.86
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
#1

Производный класс. Перегрузка << (cout). - C++

18.01.2012, 20:35. Просмотров 1891. Ответов 26
Метки нет (Все метки)

При инициализации массива указателей базового класса при вызове cout производный класс не отображается, отображается базовый. Без указателей все в порядке. Подскажите пожалуйста почему.
Вот пример кода:

bor.h
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
#include <iostream>
 
class Port
{
private:
    char * brand;   // название
    char * style;   // тип
    int bottles;    // бутылки
protected:
    const char * Brand() const {return brand;}
    const int Bottles() const {return bottles;} 
public:
    Port();
    Port(const char * br, const char * st, int b);
    Port(const Port & p);
    virtual~Port();
    Port & operator = (const Port & p);
    Port & operator += (int b);
    Port & operator -= (int b);
    int BottleCont()const {return bottles;}
    virtual void Show() const;
    friend std::ostream & operator<<(std::ostream & os, const Port & p);
};
 
class VintagePort : public Port
{
private:
    char * nickname;    // старый или новый
    int year;           // год
public:
    VintagePort();
    VintagePort(const char *br, int b, const char *nn, int y);
    VintagePort(const VintagePort & vp);
    ~VintagePort();
    VintagePort & operator= (const VintagePort & vp);
    void Show() const;
    friend std::ostream & operator<<(std::ostream & os, const VintagePort & vp);
};
bor.cpp
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
#include "bor.h"
 
// методы Port
Port::Port()
{
    char *br = "none";
    brand = new char[strlen(br)+1];
    strcpy(brand,br);
    style = new char[strlen(br)+1];
    strcpy(style,br);
    bottles = 0;    
}
Port::Port(const char * br, const char * st, int b)
{
    brand = new char[strlen(br)+1];
    strcpy(brand,br);
    style = new char[strlen(st)+1];
    strcpy(style,st);
    bottles = b;    
}
Port::Port(const Port & p)
{
    brand = new char[strlen(p.brand)+1];
    strcpy(brand,p.brand);
    style = new char[strlen(p.style)+1];
    strcpy(style,p.style);
    bottles = p.bottles;
}
Port & Port::operator = (const Port & p)
{
    if(this == &p)
        return *this;
    delete [] brand;
    delete [] style;
    brand = new char[strlen(p.brand)+1];
    strcpy(brand,p.brand);
    style = new char[strlen(p.style)+1];
    strcpy(style,p.style);
    bottles = p.bottles;
 
    return *this;
}
Port & Port::operator += (int b)
{
    bottles+=b;
    return *this;
}
Port & Port::operator -= (int b)
{
    bottles-=b;
    return *this;
}
void Port::Show() const
{
    std::cout << "Brand: " << brand << std::endl;
    std::cout << "Kind: " << style << std::endl;
    std::cout << "Bottles: " << bottles;
}
std::ostream & operator<<(std::ostream & os, const Port & p)
{
    os << p.brand << ", " << p.style << ", " << p.bottles;
 
    return os;
}
 
Port::~Port() 
{
    delete [] brand; 
    delete [] style; 
}
 
// методы VintagePort
VintagePort::VintagePort():Port()
{
    nickname = new char [5];
    strcpy(nickname,"none");
    year = 0;
}
 
VintagePort::VintagePort(const char *br, int b, const char *nn, int y):Port(br,"none",b)
{
    nickname = new char[strlen(nn)+1];
    strcpy(nickname,nn);
    year = y;
}
VintagePort::VintagePort(const VintagePort & vp) : Port(vp)
{
    nickname = new char[strlen(vp.nickname)+1];
    strcpy(nickname,vp.nickname);
    year = vp.year;
}
VintagePort & VintagePort::operator= (const VintagePort & vp)
{
    if(this == &vp)
        return *this;
    Port::operator=(vp);
    delete [] nickname;
    nickname = new char[strlen(vp.nickname)+1];
    strcpy(nickname,vp.nickname);
    year = vp.year;
 
}
void VintagePort::Show() const
{
    std::cout << "Название: " << Brand() << std::endl;
    std::cout << "Kоличество бутылок: " << Bottles() << std::endl;
    std::cout << "Старое или новое: " << nickname << std::endl;
    std::cout << "Год: " << year;
}
std::ostream & operator<<(std::ostream & os, const VintagePort & vp)
{
    os << (const Port &)vp;
    os << ", " << vp.nickname << ", " << vp.year;
    return os;
}
 
VintagePort::~VintagePort() 
{
    delete [] nickname;
}
main.cpp
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
#include <iostream>
#include "bor.h"
 
const int SIZE = 2;
 
int main()
{
    setlocale (LC_ALL, "rus");
    using std::cout;
    using std::endl;
    using std::cin;
 
            char ch[40];
            char ch2[40];
            int reiting;
            int reiting2;
            int i;
 
    Port *mass [SIZE];
 
    for(i=0; i<SIZE; i++)
    {
        char letter;
        if(i!=0)
            cout << endl;
        cout << "Введите что пишем:\nPort - A, VintagePort - B, Выход - С: ";
        cin >> letter;
        if((letter<65||letter>67)&&(letter<97||letter>99))
        {i--; cin.getline(ch,40); continue;}
        cin.get();
        if(letter == 'C' || letter == 'c')
            break;
 
        switch(letter)
        {
        case 'A':
        case 'a':
            cout << "\nPort:\n";
            cout << "Введите название: ";
            cin.getline(ch,40);
            cout << "Введите тип: ";
            cin.getline(ch2,40);
            cout << "Введите количества бутылок: ";
            cin>>reiting;
 
            mass[i] = new Port(ch,ch2,reiting);
            break;
        case 'B':
        case 'b':
            cout << "\nVintagePort:\n";
            cout << "Введите название: ";
            cin.getline(ch2,40);
            cout << "Введите количество бутылок: ";
            cin >> reiting2;
            cin.get();
            cout << "Введите старый или новый: ";
            cin.getline(ch,40);
            cout << "Введите год: ";
            cin>>reiting;
 
            mass[i] = new VintagePort(ch2,reiting2,ch,reiting);
            break;
        }
    }
    
    if(i!=0)
    {
    cout << endl << endl;
    for(int i=0; i<SIZE; i++){
        mass[i]->Show();
    cout << endl << endl;
    }
 
    //cout << *(mass[0]) << endl;   // отображает Port в любом случае
 
    for(int j=0; j<SIZE; j++)
    {
        delete mass[j];
    }
    }
 
    cout << "By :)\n\n";
 
    system("pause");
    return 0;
}
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.01.2012, 20:35
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Производный класс. Перегрузка << (cout). (C++):

Разработать производный от абстрактного класса Figure класс и класс, производный от производного - C++
Разработать базовый абстрактный класс Figure с пустым виртуальным методом print для вывода в дальнейшем полной информации об объекте: ...

Есть производный класс и базовый; при чём производный использует только ЧАСТЬ ресурсов базового, правильно ли это? - C++
Ну то есть базовый класс A, с полями, допустим, a, b, c, d. И я проектирую производный класс B и я железно знаю, что он будет использовать...

Создать класс Point и производный класс ColoredPoint (цветная точка) - C++
Создайте класс Point (точка на плоскости), характеризующийся двумя координатами. Создайте производный класс ColoredPoint (цветная точка), в...

Разработать класс Tableware (посуда) и производный класс Dish (тарелка). Описать атрибуты - C++
Разработать класс Tableware (посуда) и производный класс Dish (тарелка). Описать атрибуты.

Разработать класс Man (человек) и производный класс Student (студент). Описать атрибуты. - C++
Разработать класс Man (человек) и производный класс Student (студент). Описать атрибуты.

Создать базовый класс - Array и производный класс - Money для работы денежной суммы - C++
ПОМОГИТЕ, ПОЖАЛУЙСТА, С ЗАДАЧЕЙ Создать базовый класс - Array и производный класс - Money для работы денежной суммы

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 20:54 #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
Введите что пишем:
Port - A, VintagePort - B, Выход - С: A
 
Port:
Введите название: qw
Введите тип: as
Введите количества бутылок: 2
 
Введите что пишем:
Port - A, VintagePort - B, Выход - С: B
 
VintagePort:
Введите название: rt
Введите количество бутылок: 6
Введите старый или новый: n
Введите год: 1234
 
 
Brand: qw
Kind: as
Bottles: 2
 
Название: rt
Kоличество бутылок: 6
Старое или новое: n
Год: 1234
 
By :)
 
Для продолжения нажмите любую клавишу . . .

Вот что я получил, правильно?
1
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
18.01.2012, 21:01  [ТС] #3
kravam, Да, если VintagePort попробовать вывести через cout выведен будет Port...
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 21:11 #4
Вот я щас расскоментил cout
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
Введите что пишем:
Port - A, VintagePort - B, Выход - С: A
 
Port:
Введите название: Q
Введите тип: W
Введите количества бутылок: 11
 
Введите что пишем:
Port - A, VintagePort - B, Выход - С: B
 
VintagePort:
Введите название: A
Введите количество бутылок: 12
Введите старый или новый: n
Введите год: 34
 
 
Brand: Q
Kind: W
Bottles: 11
 
Название: A
Kоличество бутылок: 12
Старое или новое: n
Год: 34
 
Q, W, 11
By :)
 
Для продолжения нажмите любую клавишу . . .
А что должно быть по задумке?
1
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
18.01.2012, 21:17  [ТС] #5
kravam, в общем cout должен работать как Show();
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 21:26 #6
Я щас буду работать, буду автоматизирвать ввод (чтоб не вводить руками каждый раз), буду убирать ввод не нужных данных (это всё ты должен был сделать, дабы код был прост), мне нужно знать что можно убрать для нахождения тык скыть ошибки, а что нельзя. Буду это делать пошагово, пока ошибка не исчезнет. Таким образом, я упрощу код, а уже в простом коде буду искать ошибку.
И каждый после очередного упрощения, мне нужно знать- исчезла ошибка или нет; для этого я буду смотреть на вывод. А каким должен быть вывод, я от тебя не могу добиться.

Каким должен быть вывод? Предлагаю остановиться на тех данных, что я ввёл. Какого вывода ты ждёшь при этих данных? Просто нарисуй и всё.
1
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
18.01.2012, 21:39  [ТС] #7
kravam, cout выводит в строку все данные для своего типа как Show только в строку и без подписей)
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 21:52 #8
Я не знаю, что такое свой тип для cout. Для того, чтобы узнать, я должен упростить код. А чтобы упростить код правильно, мне нужно каждый раз после очередного упрощения смотреть- исчезла ошибка или нет. А для этого я должен знать, что ты ожидаешь чтобы cout выводил. И вот когда я буду знать это, я смогу упростить код, а потом уже глядя на просттой код я узнаю, что такое "свой тип для cout"

Всё упирается в то, что должен вывести cout по задумке для предлагаемых данных.
1
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
18.01.2012, 21:52  [ТС] #9
kravam, Вот так: )
0
Миниатюры
Производный класс. Перегрузка << (cout).  
DU
1483 / 1059 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
18.01.2012, 22:08 #10
ф-ия вывода в поток не вируальная.
чтобы вывод в поток зависил от динамического типа объекта, а не от статического, вывод тоже должен быть виртуальной ф-ией. в книжках обычно советуют поступать так:

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
class Base
{
public:
   virtual void Print(std::ostream& out) const
   {
      // тут имплемент печати базового класса
   }
};
 
class Derivated : public Base
{
public:
   virtual void Print(std::ostream& out) const
   {
      // тут имплемент печати производного класса
   }
};
 
std::ostream& operator << (std::ostream& out, const Base& base)
{
   // вот в таком случае если base ссылается на производный класс, то будет вызвана
   // ф-ия печати производного класса если она в нем переопределена.
   base.Print(out);
   return out;
}
1
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 22:19 #11
KeyGen, чё-то я не понял, у тебя mass указывает на массив элементов типа Port, нулевой из которых- элемент типа Port, так ты его и получаешь по рисунку это видно. Так, а в массиве mass элемент типа VintagePort это ПЕРВЫЙ элемент. Ты хочешь получить его данные? Ну так напиши
C++
1
cout << *(mass[1]) << endl;
И всё будет круто, или я чего-то не понимаю?
0
KeyGen
384 / 291 / 6
Регистрация: 07.08.2011
Сообщений: 789
Записей в блоге: 1
18.01.2012, 22:24  [ТС] #12
kravam, я так и писал вывод как на картинке
C++
1
2
3
4
5
6
...
    cout << "Ввывод Port:\n";
    cout << *(mass[0]);
    cout << "\n\nВывод VintagePort:\n";
    cout << *(mass[1]) << endl;
...
0
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 22:50 #13
Ну и всё нормально, если ты хочешь чтобы mass[0] указывал на первый элемент сделай просто


C++
1
2
3
4
5
6
7
8
9
       cout << *(mass[0]) << endl; 
        mass[0]= mass[1];
        cout << *(mass[0]) << endl;  
 
 
        for(int j=0; j<SIZE_- 1; j++)
        {
                delete mass[j];
        }
0
DU
1483 / 1059 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
18.01.2012, 22:51 #14
еще раз попробую объяснить
вот какой у вас оператор <<
C++
1
2
3
4
5
6
std::ostream & operator<<(std::ostream & os, const Port & p)
{
        os << p.brand << ", " << p.style << ", " << p.bottles;
 
        return os;
}
Это свободная ф-ия и она не вызывает никаких виртуальных методов у класса Port. Она всегда будет выводить поля просто порта, даже если p ссылается на объект VintagePort.
Т.к. у вас массив указателей на объекты типа порт, то тип выражения *mass[1] - const Port&;
Поэтому всегда будет вызываться оператор << для порта а не для винтажного порта, даже если там указатель на винтажный порт.

Если вы сделаете по примеру, который я написал выше, то у вас все заработает так, как вы хотите. Если p ссылается на винтажный порт, то позовется ф-ия печати винтажного порта (потому что она виртуальная и переопределена в винтажном порте)
1
kravam
быдлокодер
1695 / 882 / 45
Регистрация: 04.06.2008
Сообщений: 5,459
18.01.2012, 23:09 #15
Цитата Сообщение от DU Посмотреть сообщение
Поэтому всегда будет вызываться оператор << для порта а не для винтажного порта, даже если там указатель на винтажный порт.
Да для винтажного она вызывается, для винтажного. mass [1] указывает на винтажный порт, напишите
C++
1
         cout << *(mass[1]) << endl;
и увидите, данные винтажного порта выводятся или нет

Добавлено через 8 минут
Вот же написано:
C++
1
  mass[i] = new VintagePort(ch2,reiting2,ch,reiting);
И ходя выше задекларировано, что mass[i] указывает на Port, но происходит переопределение типа и происходит корректно, надо сказать, ибо Port- родителський класс. Так что всё просто; с этого момента mass [i] (mass[1]) указывает на винтажный порт!
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.01.2012, 23:09
Привет! Вот еще темы с ответами:

Создать базовый класс Car (машина) и производный класс Lorry (грузовик): ООП ошибки - C++
Создать базовый класс Car (машина), характеризуемый торговой маркой (строка), числом цилиндров, мощностью. Определить методы переназначения...

Создать базовый класс Triad и производный класс vector3D - C++
Помогите пожалуйста с заданием. Часть кода(vector3D) сделал, вроде работает Нужно помочь с классом Triad. Вот полное задание: ...

Указатели в базовом классе на базовый класс и производный класс - C++
Пишу контейнер &quot;Бинарное дерево поиска&quot; для частотного словаря. С самим контейнером особо вопросов нету. Вопрос по поводу элементов в...

Наследование: базовый класс Квадрат, производный класс Пирамида - C++
Помогите, пожалуйста!:cry: Добавлено через 6 минут Создать класс КВАДРАТ, член класса- длинна стороны. Предусмотреть в классе методы...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
18.01.2012, 23:09
Ответ Создать тему
Опции темы

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