Наследование и чистые виртуальные функции

Я изучаю наследование в С++, и я новичок в абстрагировании чистых виртуальных, базовых и производных классов. Итак, я придумал этот код ниже, он работает, но я не уверен, правильно ли я реализую принципы С++. Пожалуйста, может кто-нибудь оценить приведенный ниже код для улучшения.

#include <iostream>
using namespace std;

class Pizza
{
   private:
       double pCost;
       double pPrice;

   public:
       Pizza(const double& c, const double& p) : pCost(c), pPrice(p){}
       virtual ~Pizza(){}
       virtual double area() = 0;
       virtual double cost() = 0;
       virtual double price () = 0;
       virtual double profit() = 0;
       double getCost() const {return pCost;}
       double getPrice() const {return pPrice;}
};

class CircularPizza : public Pizza
{
   private:
       double radius;

   public:
       CircularPizza(const double& r, const double& c, const double& p)
        : Pizza(c, p), radius(r){}
        virtual ~CircularPizza(){}
        virtual double area(){ return (3.14 * radius * radius);}
        virtual double cost() { return area() * getCost(); }
        virtual double price() { return area() * getPrice(); }
        virtual double profit() { return price() - cost();}
};

person newbieLinuxCpp    schedule 08.08.2012    source источник
comment
Возможно, вам лучше будет спросить здесь. Сайт предназначен для проверки кода.   -  person ChiefTwoPencils    schedule 09.08.2012


Ответы (4)


Если бы мне нужно было что-то изменить, я бы сделал cost(), price() и profit() невиртуальными и определил их в базовом классе Pizza.

Это имеет смысл, потому что все они зависят от области — это единственное, что действительно определяет CircularPizza. Если бы вы делали класс RectangularPizza, стоимость за площадь, цена за площадь, расчет прибыли был бы таким же. Единственное, что изменится, так это сам район. Понимание этого факта должно привести вас к одинаковому дизайну классов, где изменяется только область, а другой код является общим как для CircularPizza, так и для RectangularPizza с использованием базового класса.

person hcarver    schedule 08.08.2012
comment
СПАСИБО, теперь я лучше понимаю :) - person newbieLinuxCpp; 09.08.2012
comment
И @paddy прав насчет твоего имени. Переименование getCost() в getCostPerUnitArea() и то же самое для getPrice() сделало бы его более понятным. - person hcarver; 09.08.2012

Выглядит нормально... Однако странно иметь метод getCost(), а также cost(). То же самое и с ценой... Если весь смысл функций стоимости и цены зависит от реализации, то предоставление доступа к внутренним членам pCost и pPrice кажется неправильным.

Может быть, дело только в названии? Поскольку вы указываете стоимость и цену в конструкторе, достаточно, чтобы иметь возможность запросить их позже. Так что в этом случае есть семантическая проблема (во всяком случае, на мой взгляд) с именами участников cost() и price(). Или, возможно, вы имеете в виду что-то вроде «стоимость единицы» и «общая стоимость».

Возможно, вы захотите сделать переменные-члены защищенными, а не частными.

С точки зрения вашего C++ все выглядит нормально, за исключением того, что, возможно, эти виртуальные функции должны быть постоянными, если они не изменяют класс (таким образом, их можно вызывать в константном экземпляре класса).

Кроме того, для полноты вы можете реализовать функцию CircularPizza::getRadius(), чтобы она соответствовала функциям, предоставляемым классом Pizza.

person paddy    schedule 08.08.2012
comment
Да, вы правы, мне нужно внести эти изменения. благодарю вас. - person newbieLinuxCpp; 09.08.2012

Для домашнего задания выглядит нормально. Для дополнительного чтения рассмотрите это о том, когда использовать частные виртуальные функции. Кроме того, я считаю полезным иногда создавать интерфейсы, подобные C#. .

person Jerdak    schedule 08.08.2012

Еще один момент, о котором стоит упомянуть, заключается в том, что функции area(), cost(), price() и profit() в объекте CircularPizza не обязательно должны быть виртуальными, если только вы не собираетесь использовать CircularPizza в качестве базового класса для другого производного класса. .

person Ed James    schedule 02.07.2015