0

私はまだ抽象基本クラスを完全には理解していません。これは私が割り当てのために作成したものであり、派生クラスを通じて追加されたものを何も返さないことを除いて、ほとんど機能しているようです。hasDMAまたはlacksDMAを選択するたびに、色またはスタイルから結果が返されません。

メイン.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
4

1 に答える 1

0

コメントで、「Color:」という文字列が表示されるとのことでしたが、入力例の「red」は表示されません。「Color:」が表示されるため、これはコードの抽象/仮想部分で何かが失敗したという問題ではありません (それ以外の場合は、「Color:」でさえ表示されません)。

失敗は入力にあります。「1」または「2」の選択を読み取ると、その 1 文字しか読み取れませんが、ユーザーは実際には追加の改行も入力したため、 nextcin.getlineはこの余分な改行を消費して空の文字列を返します。cin.getline入力が 1 文字であっても、入力が数値であっても、すべての入力に固執する必要があります。をまったく使用せずcin >>、入力のエラーを自分で処理する方が、うまくいかない場合にすべての境界ケースを混ぜoperator>>て処理するよりも簡単です。getline

これは答えの一部ではありませんが、一般的なアドバイスをいくつか示します。

1) C++ では、new char[x]可能な限り避けてください。std::string文字列やstd::vector<char>、非常にまれなケースstd::stringで十分でない 場合に使用します。

delete [] label1b)のデストラクタで を忘れましたABC。であれば、std::stringこれらのことを心配する必要はありません。

2)use namespace stdソース ファイル (.cpp) では問題あり#includesませんが、ヘッダー ファイル (.h) では使用しないでください。一度もない!ヘッダー ファイルでフル ネームを使用する ( のstd::string代わりに のようにstring)

編集:したがって、いくつかのコード例が必要です。私が言ったように、入力が 1 文字であっても、入力が整数であっても、 に固執しcin.getline、 を避けてください。operator>>

cin >> temprate;行を次のように置き換えます。

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

whileループの 2 行を置き換えます

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

with exit のこれらの行をfor途中で使用します(無限ループの私の好みの方法):

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

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

        cout << "Enter 1, 2: ";
    }
于 2013-10-05T12:16:25.530 に答える