Некоторые рекомендации по C ++ и созданию объектов с использованием композиции - PullRequest
0 голосов
/ 06 апреля 2019

В основном моя проблема с композициями.Я понимаю принцип, но я борюсь с выполнением в одном из тестов.

Из кода Computer и Monitor ниже я должен создать окончательный класс Complect, который будетиметь собственное имя, имя компьютера, название монитора и цену, которая будет составлена ​​из функций price().

Computer.h

#ifndef COMPUTER_H
#define COMPUTER_H
#include <string>

class Computer{

public:
    Computer(std::string name, int ram, double price); 

    std::string name() const; 
    int ram() const;
    double price() const;


    void printComputer() const;

    void setComputer(std::string name, int ram, double price);

private:
    std::string its_name;
    int ram_gb;

    double cost_price;
};
#endif // COMPUTER_H

Computer.cpp

#include "Computer.h"
#include <iostream>

Computer::Computer(std::string name, int ram, double price)
: its_name(name), ram_gb(ram), cost_price(price){
}

std::string Computer::name() const {
    return its_name;
}

int Computer::ram() const {
    return ram_gb;
}

double Computer::price() const {
    return cost_price;
}

void Computer::printComputer() const{ 
    std::cout << "Computer name = " <<name() <<"\n"
    << "Computer RAM = " <<ram() <<" GB\n"
    << "Computer Price = " << price() <<" EUR \n";
}

Monitor.h

#ifndef MONITOR_H
#define MONITOR_H
#include <string>

class Monitor{

public:
    Monitor(std::string name, std::string type, double price);

    std::string name() const;
    std::string type() const;
    double price() const;

    //print computer
    void printMonitor() const;

    //set computer
    void setMonitor(std::string name, std::string type, double price);

private:
    std::string its_name;
    std::string type_set;

    double cost_price;
};

#endif // MONITOR_H

Monitor.cpp

#include "Monitor.h"
#include <iostream>

Monitor::Monitor(std::string name, std::string type, double price) : its_name(name), type_set(type), cost_price(price){
}

std::string Monitor::name() const {
    return its_name;
}

std::string Monitor::type() const{
    return type_set;
}

double Monitor::price() const {
    return cost_price;
}

void Monitor::printMonitor() const{
    std::cout << "Monitor name = " <<name() <<"\n"
    << "Monitor type = " <<type() <<"\n"
    << "Monitor price = " << price() <<" EUR \n";
}

Вот класс, который я создал:

Complect.h

#ifndef COMPLECT_H
#define COMPLECT_H
#include <string>

class Complect{

public:
    Complect(std::string name, std::string computername, std::string monitorname,  double price);
    std::string name() const;
    std::string computername() const;
    std::string monitorname() const;
    double price() const;

    void printComplect();

    void setComplect(std::string name, std::string computername, std::string monitorname, double price);

private:
    std::string complect_name;
    std::string computername_final;
    std::string monitorname_final;
    double cost_price;

};

#endif // COMPLECT_H

Complect.cpp

#include "Complect.h"
#include "Monitor.h"
#include "Computer.h"
#include <iostream>

Complect::Complect(std::string name, std::string computername, std::string monitorname, double price) :
complect_name(name), computername_final(computername), monitorname_final(monitorname), cost_price(price){
}

std::string Complect::name() const{
    return complect_name;
}

std::string Complect::computername() const{
    return computername_final;
}

std::string Complect::monitorname() const{
    return monitorname_final;
}

double Complect::price() const{
    return cost_price;
}

void Complect::printComplect(){
    std::cout << "Complect name = " << name() <<"\n"
    << "Computer name = " <<computername() <<"\n"
    <<"Monitor name = " <<monitorname() <<"\n"
    <<"Complect price = " <<price() <<" EUR \n";
}

Вот как я использую классыв Main.cpp

#include <iostream>
#include "Computer.h"
#include "Monitor.h"
#include "Complect.h"

int main(){

    Computer asus("Asus One", 8, 545.95) ;
    asus.printComputer() ; 
    std::cout << "\n";

    Monitor iiyama("Iiyama Blackhawk 27inch", "LED", 299.99);
    iiyama.printMonitor();
    std::cout <<"\n";

    Complect numberOne ("Number one complect", asus.name(), iiyama.name(), iiyama.price() + asus.price());
    numberOne.printComplect();
    std::cout <<"\n";

system ("pause");
return 0;
}

Конечный результат такой, каким он должен быть, поэтому этот код работает.Но проблема в том, что он неправильно структурирован.

В файле main.cpp вы увидите, что создается объект Complect.Но в настоящее время я предоставляю всю информацию об этом объекте при создании в файле main.cpp.

Извините, коды немного беспорядочные, но я пытаюсь обдумать это и на данный момент борюсь ... Как заставить класс в файле complect.cpp предоставить всю свою информацию?

1 Ответ

1 голос
/ 06 апреля 2019

В настоящее время вы не используете состав, но копируете атрибуты из двух других классов, и вы выполняете большую работу при вызове конструктора из main

Первое небольшое изменение в вашем коде - получение экземпляров. Компьютер и Монитор в параметре в конструкторе:

Complect(std::string name, const Computer &, const Monitor &);

Конечно, окончательная цена также вычисляется внутри этого конструктора, в main вы просто создаете комплект с его названием и его частями:

Complect numberOne ("Number one complect", asus, iiyama);

Теперь main к счастью, не нужно знать, как рассчитывается цена, иначе представьтеесли формула изменилась, и вам необходимо обновить все вызовы конструктора :-(. Способ расчета цены зависит только от Complect .

Complect numberOne ("Number one complect", asus, iiyama);

Больше, чемКонструктор setComplect необходимо обновить, чтобы получить цену монитора и компьютера, разделенных по той же причине.

void setComplect(std::string name, std::string computername, std::string monitorname, double computerprice, double monitorprice);

или, возможно, лучше заменить его методами

void setname(std::string name);
void setcomputer(std::string computername, double computerprice);
void setmonitor(std::string monitorname, double monitorprice);

Но дублировать все атрибуты Компьютер и Монитор в Комплект нецелесообразно, и у вас нетсостав к экземплярам.Первая возможность - сохранить их копию:

class Complect{
  ...
  private:
     Computer computer;
     Monitor monitor;
     // does not need attribute "double cost_price;"
  ...
};

Complect::Complect(std::string name, const Computer & c, const Monitor & m)
   : complect_name(name), computer(c), monitor(m) {
}

std::string Complect::computername() const{
    return computer.name();
}

std::string Complect::monitorname() const{
    return monitor.name();
}

double Complect::price() const{
    return computer.price() + monitor.price();
}

void Complect::printComplect(){
    std::cout << "Complect name = " << name() <<"\n"
    << "Computer name = " << computer.name() <<"\n"
    <<"Monitor name = " << monitor.name() <<"\n"
    <<"Complect price = " << price() <<" EUR \n";
}

Преимущество этого решения заключается в том, что на вас не влияют первоначальные экземпляры Monitor и Computer исчезают.Недостатком является, например, то, что цена не обновляется, если цена одной из клонированных частей изменяется, за исключением вызова setXXX


Другой способ - не клонировать монитор и компьютер., но вы не можете получить только это:

class Complect{
  ...
  private:
     Computer & computer;
     Monitor & monitor;
     // does not need attribute "double cost_price;"
  ...
};

Complect::Complect(std::string name, const Computer & c, const Monitor & m)
   : complect_name(name), computer(c), monitor(m) {
}

, потому что это предполагает, что экземпляры Monitor и Computer все еще существуют, в то время как соответствующий экземпляр Complect существует

К счастью, C ++ предлагает интересные функции для управления этим

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...