2013-10-05 6 views
0

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

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 
+3

Это слишком много кода. Пожалуйста, разместите раздел, в котором вы, похоже, проблема. – Saksham

+1

Как насчет 'std :: string' и' std :: vector' ???Ваш код полон динамического распределения ... Бог поможет тем, кто будет его отлаживать. – LihO

+0

Я не вижу никаких проблем с кодом (кроме того, что вы должны «удалить [] label' в' ABC :: ~ ABC() ', или еще лучше сделать его' std :: string'). Убедитесь, что ваш код идентичен коду, указанному здесь. Также укажите пример ввода, ожидаемого вывода и фактического вывода. – Dialecticus

ответ

0

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

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

Altough это не является частью ответа, вот некоторые общие советы:

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

Итак, в основном, когда я прошу ввода для hasDMA или отсутствия DMA, он переносит пустую строку в следующий вопрос? – user2849274

+0

Да, новая строка ввода не используется частью кода 'cin >> choice'. – Dialecticus

+0

Даже если я изменю вход для выбора целого, он все еще не работает. Я не могу понять, как получить этот вход, не перенося пустое место. – user2849274