Описать абстрактный класс Музыкальный инструмент. Класс должен содержать характеристики: название, фирма-производитель, стоимость, функцию вывода всех данных на экран. На его основе реализовать классы Духовой инструмент, Фортепиано, Струнный инструмент. Задать отдельные характеристики классов, например, год выпуска, количество струн и т.п
Создать массив объектов класса Оркестр, модифицировать его, поместив в его начало все Духовые инструменты. Создал класс оркестр и сталкиваюсь с новой проблемой. Мне нужно выводить данные записанные с помощью 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;
}
}
}
}
Класс-оркестр ничего не должен знать о конкретных инструментах, ему нужен только общий интерфейс инструментов. Для хранения списка инструментов можно использовать список указателей на инструменты, для сортировки - указать каждому инструменту приоритет, 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
, если вам так понятнее.
Наследовать члены-данные не желательно, обычно лучше наследовать методы. Это удобнее для расширения.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Возможно ли получить HANDLE с помощью QSerialPort аналогичный HANDLE получаемому с помощью CreateFile (winapi, )?
У меня есть 4 виджета : startWidget, mainWidget, student widget, teacherWidgetВ startWidget я выбираю который открыть student widget или teacherWidget и на заднем фоне у меня открыт mainWidget