Абстрактный Базовый класс не возвращается правильно

Я до сих пор не совсем понимаю базовые абстрактные классы. Это то, что я создал для своего задания, и, похоже, оно в основном работает, за исключением того, что оно не возвращает ничего, что было добавлено через производные классы. Всякий раз, когда я выбираю hasDMA или не хватает DMA, я не получаю результат, возвращаемый цветом или стилем.

main.cpp

#include <iostream>
#include <conio.h>
#include "DMA.h"
using namespace std;

const int RECORDS = 1;
const int LEN = 40;

int main()
{
ABC * p_records[RECORDS];

int i;
for (i = 0; i < RECORDS; i++)
{
char temp[LEN];
int temprate;
char choice;

cout << "\nEnter label name: ";
cin.getline(temp, LEN);
cout << "Enter Rating: ";
cin >> temprate;

cout << "Enter 1 for lacksDMA or 2 for hasDMA: ";
while (cin >> choice && (choice != '1' && choice != '2'))
cout << "Enter 1, 2: ";
if (choice == '1')
{
char tempcolor[LEN];
cout << "Enter the color: ";
cin.getline(tempcolor, LEN);
p_records[i] = new lacksDMA(temp, temprate, tempcolor);
}
else
{
char tempstyle[LEN];
cout << "Enter the style: ";
cin.getline(tempstyle, LEN);
p_records[i] = new hasDMA(tempstyle, temp, temprate);
}
while (cin.get() != '\n')
continue;
}
cout << endl;
for (i = 0; i < RECORDS; i++)
{
p_records[i]->View();
cout << endl;
}

for (i = 0; i < RECORDS; i++)
{
delete p_records[i];
}

cout << "\nPress any key to continue...";
cin.sync();
_getch();

return 0;
}

DMA.cpp

#include "DMA.h"
using namespace std;ABC::ABC(const char * l, int r)
{
label = new char [strlen(l) + 1];
strcpy(label, l);
rating = r;
}

ABC::ABC(const ABC & rs)
{
label = new char[strlen(rs.label) + 1];
strcpy(label, rs.label);
rating = rs.rating;
}

ABC::~ABC()
{
}

ABC & ABC::operator=(const ABC & rs)
{
if (this == &rs)
return *this;
delete [] label;
label = new char[strlen(rs.label) + 1];
strcpy(label, rs.label);
rating = rs.rating;
return *this;
}

ostream & operator<<(ostream & os, const ABC & rs)
{
rs.View();
return os;
}

void ABC::View() const
{
cout << "\nLabel: " << label << endl;
cout << "Rating: " << rating << endl;
}

baseDMA::baseDMA(const char * l, int r) : ABC(l,r)
{
}

lacksDMA::lacksDMA(const char * l, int r, const char * c) : ABC(l,r)
{
strncpy(color, c, 39);
color[39] = '\0';
}

lacksDMA::lacksDMA(const ABC &rs, const char * c) : ABC(rs)
{
strncpy(color, c, 39);
color[39] = '\0';
}

void lacksDMA::View() const
{
ABC::View();
cout << "Color: " << color << endl;
}

hasDMA::hasDMA(const char * s, const char * l, int r) : ABC(l,r)
{
style = new char [strlen(s) + 1];
strcpy(style, s);
}

hasDMA::hasDMA(const char * s, const ABC & rs) : ABC(rs)
{
style = new char [strlen(s) + 1];
strcpy(style, s);
}

hasDMA::hasDMA(const hasDMA & hs) : ABC(hs)
{
style = new char [strlen(hs.style) + 1];
strcpy(style, hs.style);
}

hasDMA::~hasDMA()
{
delete [] style;
}

void hasDMA::View() const
{
ABC::View();
cout << "Style: " << style << endl;
}

DMA.h

#ifndef DMA_H_
#define DMA_H_
#include <iostream>

using namespace std;

// Abstract Base Class
class ABC
{
private:
char * label;
int rating;
public:
ABC(const char * l = "null", int r = 0);
ABC(const ABC & rs);
virtual ~ABC() = 0;
virtual ABC & operator=(const ABC & rs);
virtual void View() const;
friend ostream & operator<<(ostream & os, const ABC & rs);
};

// Former Base Class Using DMA
class baseDMA: public ABC
{
private:

public:
baseDMA(const char * l = "null", int r = 0);
};

// derived class without DMA
// no destructor needed
// uses implicit copy constructor
// uses implicit assignment operator
class lacksDMA : public ABC
{
private:
char color[40];
public:
lacksDMA(const char * l = "null", int r = 0, const char * c = "blank");
lacksDMA(const ABC & rs, const char * c);
virtual void View() const;
};

// derived class with DMA
class hasDMA : public ABC
{
private:
char * style;
public:
hasDMA(const char * s = "none", const char * l = "null", int r = 0);
hasDMA(const char * s, const ABC & rs);
hasDMA(const hasDMA & hs);
~hasDMA();
hasDMA & operator = (const hasDMA & rs);
void View() const;
};

#endif

0

Решение

В комментариях вы сказали, что отображается строка «Color:», но пример ввода «красный» не отображается. Поскольку отображается «Color:», это не является проблемой чего-то неуспешного в абстрактной / виртуальной части кода (в противном случае даже «Color:» не будет отображаться).

Ошибка на входе. Когда вы читаете выбор «1» или «2», вы читаете только этот один символ, но пользователь фактически также вводит дополнительную новую строку и так далее cin.getline будет использовать эту дополнительную новую строку и вернет пустую строку. Вы должны придерживаться cin.getline для всех вводимых данных, даже если ввод представляет собой только один символ, и даже если ввод представляет собой число. Легче никогда не использовать cin >>и обрабатывать ошибки ввода самостоятельно, чем смешивать operator>> с getline а затем обрабатывать все пограничные случаи, когда они не играют хорошо вместе.

Хотя это не часть ответа, вот несколько общих советов:

1) В C ++ избегайте new char[x] когда возможно. использование std::string для строк и std::vector<char> для очень редких случаев, когда std::string не достаточно хорош

1b) Вы забыли delete [] label в деструкторе ABC, Если бы это было std::string вам не придется беспокоиться об этих вещах.

2) Это нормально, чтобы use namespace std в исходных файлах (.cpp), и только после того, как все #includes, но никогда не используйте его в заголовочных файлах (.h). Никогда! Используйте полные имена в заголовочных файлах (например, std::string вместо string)

РЕДАКТИРОВАТЬ: Итак, некоторый пример кода не требуется. Как я уже сказал, придерживайтесь cin.getlineи избегать operator>>, даже если ввод только один символ, и даже если ввод является целым числом:

Заменить линию cin >> temprate; с этим:

    cin.getline(temp, LEN);
temprate = strtol(temp, NULL, 10);

Заменить две строки while петля

    while (cin >> choice && (choice != '1' && choice != '2'))
cout << "Enter 1, 2: ";

с этими линиями for с выходом посередине (мой любимый способ бесконечного зацикливания):

    for (;;)
{
cin.getline(temp, LEN);
choice = temp[0];

if (choice == '1' || choice == '2')
break;

cout << "Enter 1, 2: ";
}
0

Другие решения

Других решений пока нет …