Есть ли способ сделать так, чтобы производный класс не наследовал все члены базового класса?

#c #class #inheritance

Вопрос:

Поэтому у меня есть elipse в качестве базового класса, в котором в качестве членов есть два двойника, которые представляют два радиуса. Я хочу вывести из него класс circle. Кругу нужен только один радиус в качестве члена, но он все равно наследует два от elipse. Я чувствую, что зря трачу память. В данном конкретном случае это не так уж важно, но я думаю, что в других контекстах это может быть.
p.s. elipse также является производным от класса figure, который является интерфейсом

Вот заголовки 3 классов:

рисунок.h

  #pragma once
 #define PI 3.1415
class figure
{
public:
    virtual double area() = 0;
    virtual double perimeter() = 0;
};
 

элипс.ч

 #pragma once
#include "figure.h"

class elipse : public figure
{
protected:
    double radius1, radius2;

public:
    elipse(double radius1 = 0, double radius2 = 0);
    
    void set_radius1(double);
    void set_radius2(double);
    double get_radius1();
    double get_radius2();

    double area() override;
    double perimeter() override;
};
 

круг.ч

 #pragma once
#include "elipse.h"

class circle:
    private elipse
{
public:
    circle(double radius = 0);
    double perimeter() override;
    double area() override;

    double get_radius();
    void set_radius(double);
};
 

Вот реализация метода set_radius, чтобы показать, что мне все еще нужно установить два радиуса, даже если теоретически мне нужен один.

 void circle::set_radius(double radius)
{
    set_radius1(radius);
    set_radius2(radius);
}
 

Комментарии:

1. Нет. Если вас так беспокоит пространство, то унаследуйте его непосредственно от рисунка.

2. Я не понимаю, почему вы не идете противоположным путем в своей иерархии. Т. е. рисунок ==> круг ==>> elipse, где вы добавляете второй радиус в >> elipse вместо того, чтобы пытаться скрыть ненужный радиус от circle

3. Я думал об этом, но на самом деле это не имеет смысла, потому что circle-это частный случай elipse, а не наоборот

4. Наследование @WhozCraig обычно представляет собой отношение «есть-а». Эллипс-это не круг.

5. Не уверен, следует ли вам создавать один из circle подклассов или ellipse подклассы другого. Математически может существовать связь «есть» между circle и ellipse , но в вашей программе она не обязательно есть: ни один circle::get_radius() , ни ellipse::get_radius1() другие не являются частью обоих классов, поэтому ни одна операция, доступная для одного из типов, не является подмножеством другого. Возможно,вам будет лучше перенести логику вычисления производных свойств во вспомогательные функции, то есть, если вы вообще хотите поделиться логикой;другим вариантом было бы разрешить ellipse c = ellipse::create_circle(r); (без круга типов)

Ответ №1:

Это невозможно. Когда вы производите circle от ellipse , под капотом это очень похоже на добавление переменной-члена типа circle в ellipse . (И вы также не можете добавить половину a circle в качестве переменной-члена.)

Возможное решение (которое не обязательно более эффективно) состоит в том , чтобы создать абстрактный класс, производный от figure , с чистыми виртуальными геттерами для двух радиусов и area() реализованный в их терминах. Затем circle и ellipse может быть как производным от этого класса, добавляя переменные-члены для радиусов, задатчики для них и переопределяя получатели. Решение о том, что с perimeter() этим делать, остается в качестве упражнения для читателя.