Массив объектов класса

249
20 мая 2018, 23:20

Описать абстрактный класс Музыкальный инструмент. Класс должен содержать характеристики: название, фирма-производитель, стоимость, функцию вывода всех данных на экран. На его основе реализовать классы Духовой инструмент, Фортепиано, Струнный инструмент. Задать отдельные характеристики классов, например, год выпуска, количество струн и т.п

Создать массив объектов класса Оркестр, модифицировать его, поместив в его начало все Духовые инструменты. Создал класс оркестр и сталкиваюсь с новой проблемой. Мне нужно выводить данные записанные с помощью Case 1, но как их использовать правильно в Case 3, при этом поставив все духовые на первое место просто не знаю.

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <stdio.h>
#include <string>
using namespace std;
//Класс музыкальные инструменты
class instrument
{
protected:
    string name, firm;
    int cost;
public:     
    instrument(): name("NULL"), firm("NULL"), cost(0)
    {}
    virtual ~instrument() = default;
    void GetInst()
    {
        cout << "\nВведите название инструмента: "; cin >> name;
        cout << "Введите производителя: "; cin >> firm;
        cout << "Введите цену: "; cin >> cost;
    }
    void PutInst()
    {
        cout << "\nИнструмент: " << name;
        cout << "\nПроизводитель: " << firm;
        cout << "\nЦена: " << cost;     
    }
    virtual void GetData() = 0; 
    virtual void PutData() = 0;
};
//Духовые инструменты
class WindInst: public instrument
{
protected:
    int year, LC; //LC - длина канала
    string material, color; 
public:
    WindInst(): material("Metal"), color("White"), year(2018), LC(0)
    {}
    void GetData()
    {
        cout << "\nДуховой" << endl;
        instrument::GetInst();
        cout << "Введите год: "; cin >> year;  
        cout << "Введите длину канала духового инструмента: "; cin >> LC;
        cout << "Введите материал: "; cin >> material;
        cout << "Введите цвет: "; cin >> color;
    }
    void PutData()
    {
        cout << "\nДуховой" << endl;
        instrument::PutInst();
        cout << "\nГод: " << year; 
        cout << "\nДлина духового канала: " << LC;
        cout << "\nМатериал: " << material;
        cout << "\nЦвет: " << color << endl;
    }               
};
//Фортепиано
class PianoInst: public instrument
{
protected:
    int year;
    const int NON, key;
    string material;
public:
    PianoInst(): key(85), NON(7), material("Tree"), year(2018)
    {}
    void GetData()
    {
        cout << "\nКлавишный" << endl;
        instrument::GetInst();
        cout << "Введите год: "; cin >> year;  
        cout << "Введите материал: "; cin >> material;
    }
    void PutData()
    {
        cout << "\nКлавишный" << endl;
        instrument::PutInst();
        cout << "\nГод: " << year; 
        cout << "\nКоличество нот: " << NON;
        cout << "\nКоличество клавиш: " << key;
        cout << "\nМатериал: " << material << endl;
    }               
};
//Струнные инструменты
class StringInst: public instrument
{
protected:
    int year, NOS; //Количество струн (NOS)
    string material, color;
public:
    StringInst(): material("Steel"), color("Red"), year(2018), NOS(0)
    {}
    void GetData()
    {
        cout << "\nСтрунный" << endl;
        instrument::GetInst();
        cout << "Введите год: "; cin >> year;  
        cout << "Введите количество струн: "; cin >> NOS;
        cout << "Введите материал: "; cin >> material;
        cout << "Введите цвет: "; cin >> color;
    }
    void PutData()
    {
        cout << "\nСтрунный" << endl;
        instrument::PutInst();
        cout << "\nГод: " << year; 
        cout << "\nКоличество струн: " << NOS;
        cout << "\nМатериал: " << material;
        cout << "\nЦвет: " << color << endl;    
    }
};
class Orchestra: public instrument
{
private:
    WindInst mass1[100];
    int n1;
    PianoInst mass2[100];
    int n2;
    StringInst mass3[100];
    int n3;
public:
    Orchestra()
    {
        n1 = 0;
        n2 = 0;
        n3 = 0;
    }
    void print()
    {
        for (int i = 0; i < n1; i++){
            cout << endl;
            mass1[i].PutData();
            cout << endl;
        }
        for (int i = 0; i < n2; i++){
            cout << endl;
            mass2[i].PutData();
            cout << endl;
        }
        for (int i = 0; i < n3; i++){
            cout << endl;
            mass3[i].PutData();
            cout << endl;
        }
    }
};
int main()
{
    setlocale(LC_ALL,"Russian");
    system ("chcp 1251 && cls");
    srand(time(NULL));
    int n = 0, s = -1, h=2;
    bool k = true;
    char choice;
    instrument* instK[h];
    WindInst w;
    PianoInst p;
    StringInst st; 
    Orchestra* mass[h];
    while(true){
    cout << "     Выберите дальнейшее действие: " << endl;
    cout << "1) Ввод инструментов" << endl;
    cout << "2) Вывод всех инструментов" << endl;
    cout << "3) Оркестр" << endl;
    cout << "0) Выход" << endl << endl;
    cout << "S=";
    cin >> s;
    system("cls");
    switch(s) {
    //Ввод инструментов
    case 1: {   
    do{
        cout << "Духовой (W), Струнный (S) или Клавишный(P): ";
        cin >> choice;
        if(choice == 'W' || choice == 'w')
        {
            instK[n] = new WindInst;
            h++;
        }
        else if(choice == 'S' || choice == 's')
        {
            instK[n] = new StringInst;
            h++;
        }
        else
        {
            instK[n] = new PianoInst;
            h++;
        }
        instK[n++] -> GetData();
        cout << "Ещё инструмент (y/n)?";
        cin >> choice;
        system("cls");
    }
    while(choice == 'y');
    system("cls");
    break;
    }
    //Вывод всех данных на экран
    case 2:{
    for(int j=0; j<n; j++)
    {
        instK[j] -> PutData();
    }
    system("pause");
    system("cls");
    break;
    }
    //Оркестр
    case 3:{
    for(int p=0; p<n; p++)
    {
        mass[p] -> print();
    }
    system("pause");
    system("cls");
    break;
    }
    //Выход
    case 0:{
    return 0;
    break;
    }
}
}
}
Answer 1

Класс-оркестр ничего не должен знать о конкретных инструментах, ему нужен только общий интерфейс инструментов. Для хранения списка инструментов можно использовать список указателей на инструменты, для сортировки - указать каждому инструменту приоритет, 0 - по умолчанию, 1 - для духовых, и сортировать по убыванию.

Вот основа:

#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
class Instrument{
public:
    virtual std::string getName() const = 0;
    virtual int getPriority() const { return 0; }
    virtual ~Instrument(){}
    bool operator < (const Instrument& rha){ // Обратите внимание, это не виртуальный метод - он одинаков дял всех инструментов
        return getPriority() < rha.getPriority(); 
    }
};
std::ostream& operator << (std::ostream& out, const Instrument& rha){
    return out << rha.getName(); // Или можно сделать виртуальный метод "void print(std::ostream&) const", и вызывать его в невиртуальном operator <<
}
class Orchestra{
public:
    void add(std::unique_ptr<Instrument> newInstrument){
        if(!newInstrument)
             return; // Нулевой указатель игнорируем
        // Функция, разыменовывающая указатели и сравнивающая значения по убыванию приоритета
        auto priorityGreather = [](const std::unique_ptr<Instrument>& lha, const std::unique_ptr<Instrument>& rha){
            return *rha < *lha;
        };
        // Ищет итератор, перед которым можно вставить новый элемент, не нарушая сортировку по priorityGreather (сортировака по убыванию приоритета)
        auto insertIt = std::lower_bound(list.begin(), list.end(), newInstrument, priorityGreather);
        // Вставляет новый элемент на это место
        list.insert(insertIt, std::move(newInstrument));
    }
    friend std::ostream& operator << (std::ostream& out, const Orchestra& rha);
private:
    std::vector<std::unique_ptr<Instrument>> list;
};
std::ostream& operator << (std::ostream& out, const Orchestra& rha){
    for(const auto& x: rha.list)
        out << *x << '\n';
    return out;
}
class WindInstruments: public Instrument{
    public:
    WindInstruments() = default;
    ~WindInstruments() override {}
    std::string getName() const override { return "WindInstruments"; }
    int getPriority() const { return Instrument::getPriority() + 1; }
};
class StringedInstruments: public Instrument{
    public:
    StringedInstruments() = default;
    ~StringedInstruments() override {}
    std::string getName() const override { return "StringedInstruments"; }
    // int getPriority() const { return Instrument::getPriority(); } // Оставляем по умолчанию
};

int main(){
   Orchestra orhestra;
   orhestra.add(std::make_unique<WindInstruments>());
   orhestra.add(std::make_unique<StringedInstruments>());
   orhestra.add(std::make_unique<StringedInstruments>());
   orhestra.add(std::make_unique<WindInstruments>());
   orhestra.add(std::make_unique<WindInstruments>());
   orhestra.add(std::make_unique<StringedInstruments>());
   orhestra.add(std::make_unique<WindInstruments>());
   std::cout << orhestra;
   return 0;
}

Вывод:

WindInstruments
WindInstruments
WindInstruments
WindInstruments
StringedInstruments
StringedInstruments
StringedInstruments

std::unique_ptr можно заменить на сырые указатели на instrument, если вам так понятнее.

Наследовать члены-данные не желательно, обычно лучше наследовать методы. Это удобнее для расширения.

READ ALSO
Возможно ли получить HANDLE с помощью QSerialPort аналогичный HANDLE получаемому с помощью CreateFile (winapi, &lt;windows.h&gt;)?

Возможно ли получить HANDLE с помощью QSerialPort аналогичный HANDLE получаемому с помощью CreateFile (winapi, <windows.h>)?

Возможно ли получить HANDLE с помощью QSerialPort аналогичный HANDLE получаемому с помощью CreateFile (winapi, )?

191
Передача файла в ф-ию c++

Передача файла в ф-ию c++

Программа останавливается на строке count = countFile(file); Почему?

235
Помогиите работа с типами данных по C++

Помогиите работа с типами данных по C++

Всем привет, помогите плз с задачкой по с++:( Суть: 1

234
Открывается два виджета одновременно

Открывается два виджета одновременно

У меня есть 4 виджета : startWidget, mainWidget, student widget, teacherWidgetВ startWidget я выбираю который открыть student widget или teacherWidget и на заднем фоне у меня открыт mainWidget

209