Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/4: Рейтинг темы: голосов - 4, средняя оценка - 4.50
0 / 0 / 0
Регистрация: 21.02.2017
Сообщений: 18
1

Неправильный вывод при работе с виртуальными функциями

21.02.2017, 17:30. Просмотров 835. Ответов 10
Метки нет (Все метки)

В общем, учу плюсы по книге Праты. Там есть одно задание по виртуальным функциям. Но дело сейчас не в них.
У меня есть базовый (Cd) и производный (Classic) классы. Есть все нужные конструкторы.
C++
1
2
3
4
5
6
7
Cd::Cd(char * s1, char * s2, int n, double x)
{
    strcpy(performers,s1);
    strcpy(label,s2);
    selections = n;
    playtime = x;
}
C++
1
2
3
4
Classic::Classic(char * s1, char * s2, int n, double x, char *mt) : Cd(s1, s2, n, x)
{
    strcpy(main_theme,mt);
}
Дальше в мейне пишу это:
C++
1
2
3
4
Cd c1("Beatles", "Capitol", 14, 35.5);
Classic c2 = Classic("Alfred Brendel", "Philips", 2, 57.17, "Piano Sonata in B flat, Fantasia in C");
c1.Report();
c2.Report();
Report - это виртуальная фунция.
C++
1
2
3
4
5
6
7
8
9
10
void Cd::Report() const
{
    std::cout<<std::endl<<"Performers: "<<performers<<std::endl<<"Label: "<<label<<std::endl
            <<"Selections: "<<selections<<std::endl<<"Playtime: "<<playtime<<std::endl;
}
void Classic::Report() const
{
    Cd::Report();
    std::cout<<"Main theme: "<<main_theme<<std::endl;
}
Но по каким-то причинам у меня в результате вывода c1.Report() в поле Performers: возникает "asia in C". Вся другая информация, включая вывод c2.Report() корректная. Если не создавать объект Classic, то вывод для объекта Cd будет корректным.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.02.2017, 17:30
Ответы с готовыми решениями:

Неправильный вывод при работе с файлом
Возникла непонятка при выводе на экран текстового файла. У меня имеется файл с последовательностью...

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

Работа с виртуальными функциями
Доброго времени суток, форумчани! Помогите мне, пожалуйста, с задачей, у меня просто нет этой темы,...

Задачка с наследованием и виртуальными функциями
Диаграмма классов на приложенном рисунке. #include &lt;iostream&gt; class IData { public:...

10
Модератор
Эксперт CЭксперт С++
3966 / 3467 / 615
Регистрация: 07.10.2015
Сообщений: 7,187
21.02.2017, 17:35 2
the_whatever, будет понятнее, если приведете весь проект
0
0 / 0 / 0
Регистрация: 21.02.2017
Сообщений: 18
21.02.2017, 17:40  [ТС] 3
Вот объявление классов
Кликните здесь для просмотра всего текста
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
// Базовый класс
class Cd { // представляет компакт-диск
private:
    char performers[50];
    char label[20];
    int selections; // количество сборников
    double playtime; // время воспроизведения в минутах
public:
    Cd(char * s1, char * s2, int n, double x);
    Cd(const Cd & d);
    Cd();
    ~Cd(){}
    virtual void Report() const; // выводит все данные о компакт-диске
    Cd & operator= (const Cd & d);
};
 
class Classic : public Cd
{
private:
    char main_theme[20];
public:
    Classic(char * s1, char * s2, int n, double x, char *mt);
    Classic(const Classic &d);
    Classic();
    ~Classic(){}
    virtual void Report() const;
};

Вот объявление методов
Кликните здесь для просмотра всего текста
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
Cd::Cd(char * s1, char * s2, int n, double x)
{
    strcpy(performers,s1);
    strcpy(label,s2);
    selections = n;
    playtime = x;
}
 
Cd::Cd(const Cd & d)
{
    strcpy(performers,d.performers);
    strcpy(label,d.label);
    selections = d.selections;
    playtime = d.playtime;
}
 
Cd::Cd()
{
    strcpy(performers,"Potap i Nastya");
    strcpy(label,"hz krch");
    selections = 5;
    playtime = 125;
}
 
void Cd::Report() const
{
    std::cout<<std::endl<<"Performers: "<<performers<<std::endl<<"Label: "<<label<<std::endl
            <<"Selections: "<<selections<<std::endl<<"Playtime: "<<playtime<<std::endl;
}
 
Cd& Cd::operator= (const Cd & d)
{
    if (this == &d)
        return *this;
    strcpy(performers,d.performers);
    strcpy(label,d.label);
    selections = d.selections;
    playtime = d.playtime;
    return *this;
}
 
Classic::Classic()
{
    strcpy(main_theme,"Chumachechaya vesna");
}
 
void Classic::Report() const
{
    Cd::Report();
    std::cout<<"Main theme: "<<main_theme<<std::endl;
}
 
Classic::Classic(char * s1, char * s2, int n, double x, char *mt) : Cd(s1, s2, n, x)
{
    strcpy(main_theme,mt);
}
 
Classic::Classic(const Classic &d):Cd(d)
{
    strcpy(main_theme,d.main_theme);
}

Вот функция main
Кликните здесь для просмотра всего текста
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
void Bravo(const Cd & disk);
int main ()
{
    Cd c1("Beatles", "Capitol", 14, 35.5);
    Classic c2 = Classic("Alfred Brendel", "Philips", 2, 57.17, "Piano Sonata in B flat, Fantasia in C");
    Cd *pcd = &c1;
    // Непосредственное использование объектов
    cout << "Using object directly:\n";
    c1.Report(); // использование метода Cd
    c2.Report(); // использование метода Classic
    
    // Использование указателя на объекты типа cd *
    cout << "Using type cd * pointer to objects: \n" ;
    pcd->Report(); // использование метода Cd для объекта cd
    pcd = &c2;
    pcd->Report (); // использование метода Classic для объекта classic
    
    // Вызов функции с аргументом-ссылкой на Cd
    cout << "Calling a function with a Cd reference argument:\n";
    Bravo(cl);
    Bravo(c2);
    // Тестирование присваивания
    cout << "Testing assignment: ";
    Classic copy;
    copy = c2;
    copy.Report();
    */
    return 0;
}
 
void Bravo (const Cd & disk)
{
    disk.Report();
}
0
1201 / 723 / 165
Регистрация: 05.12.2015
Сообщений: 2,116
21.02.2017, 18:11 4
Цитата Сообщение от the_whatever Посмотреть сообщение
"Piano Sonata in B flat, Fantasia in C"
Чему равна длина этой строки?
А куда вы ее копируете?
Микрософт не по желанию левой пятки отключил по умолчанию strcpy()
1
Модератор
Эксперт CЭксперт С++
3966 / 3467 / 615
Регистрация: 07.10.2015
Сообщений: 7,187
21.02.2017, 18:16 5
Цитата Сообщение от the_whatever Посмотреть сообщение
char main_theme[20];
вот-вот...
0
0 / 0 / 0
Регистрация: 21.02.2017
Сообщений: 18
21.02.2017, 18:20  [ТС] 6
действительно, глупая ошибка)
спасибо
но как это влияет на объект базового класса? я же копирую "Beatles" в performers[50]. Почему при конструировании объекта Classic изменяется объект Cd?
0
Модератор
Эксперт CЭксперт С++
3966 / 3467 / 615
Регистрация: 07.10.2015
Сообщений: 7,187
21.02.2017, 18:24 7
the_whatever, они в памяти находятся рядом. Переполняя строку, Вы залезаете в чужую область...
1
1201 / 723 / 165
Регистрация: 05.12.2015
Сообщений: 2,116
21.02.2017, 18:25 8
Лучший ответ Сообщение было отмечено the_whatever как решение

Решение

Цитата Сообщение от the_whatever Посмотреть сообщение
Почему при конструировании объекта Classic изменяется объект Cd
Потому, что выход за границы массива - UB. В данном случае происходит так потому, что они на стеке расположены друг за другом (как они расположатся от вас не зависит). Вы просто пишете в чужую память.
1
Модератор
Эксперт CЭксперт С++
3966 / 3467 / 615
Регистрация: 07.10.2015
Сообщений: 7,187
21.02.2017, 18:38 9
the_whatever, хорошо еще, что затерли данные.
Представьте себе, если изменятся адреса методов, адреса возврата. Это все в стеке, все рядом!
Последствия могут быть самые невероятные! Это называется "срыв стека"!
Поэтому надо всегда контролировать длину данных!
0
0 / 0 / 0
Регистрация: 21.02.2017
Сообщений: 18
21.02.2017, 18:57  [ТС] 10
Это я понимаю. Обычно я это делаю с помощью динамически выделенной памяти. А тут в условиях задания фигурировали статические массивы. Я размер-то дал символический и забыл про него)

Не по теме:

Кстати, а как перед началом ответа вставить ник человека, к которому обращаешься? Не могу кнопки нужной найти. Или вы это вручную делаете, изменяя шрифт?

0
Модератор
Эксперт CЭксперт С++
3966 / 3467 / 615
Регистрация: 07.10.2015
Сообщений: 7,187
21.02.2017, 19:01 11
Цитата Сообщение от the_whatever Посмотреть сообщение
Не по теме:
Кстати, а как перед началом ответа вставить ник человека, к которому обращаешься? Не могу кнопки нужной найти. Или вы это вручную делаете, изменяя шрифт?
the_whatever, нажать мышкой слева на ник адресата ...
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.02.2017, 19:01

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

Классы с виртуальными функциями. Class Student
Создать класс Студент со свойствами: ФИО, Факультет, Курс, минималь- ная оценка по экзаменам за...

Помощь при работе с функциями в Си++
Как правильно обратится к элементам массива в функции zam int zam(int n, int m, int**a) { int...

Реализовать абстрактный класс pair c виртуальными арифметическими функциями
Вот задание: Создать абстрактный базовый класс Pair с виртуальными арифметическими операциями....

Создать абстрактный базовый класс с виртуальными функциями - площадь и периметр
Помогите написать,не врублюсь как писать много пропустил (( Задание:Создать абстрактный базовый...


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

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

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