Может ли производный класс быть меньше, чем его родительский класс? - PullRequest
4 голосов
/ 08 мая 2020

Я спрашиваю это о C ++, так как я знаком с этим, но вопрос действительно объясняет сам себя: существует ли язык, на котором мы можем получить класс и сделать его меньше места в памяти, чем исходный класс?

Этот вопрос - скорее уловка, чем реальная проблема, которую я пытаюсь решить, но я мог представить, что некоторый действительно высокопроизводительный код может выиграть от такой оптимизации памяти:

Предположим, мы have:

class Person {
    std::string name;
    unsigned int age;
}

class PersonNamedJared {
}

Теоретически нам не нужно поле «name» в этом подклассе, поскольку оно всегда будет «Jared», что может позволить повысить эффективность использования памяти.

Есть ли единственный способ добиться этого, заменив поле «name» в Person на функцию get_name(), которую мы просто переопределим в PersonNamedJared, чтобы всегда возвращать «Jared»? Как бы мы все еще сделали переменную имени в базовом классе?

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

Ответы [ 4 ]

6 голосов
/ 08 мая 2020

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

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

Это единственный способ добиться этого, заменив поле 'name' в Person на функция get_name (), которую мы просто переопределяем в PersonNamedJared, чтобы всегда возвращать «Джаред»?

Это был бы один из способов добиться этого.

переменная имени в базовом классе?

У вас не может быть переменной-члена в базе, которая не должна быть в производном классе.

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

struct Person {
    unsigned int age;
    virtual std::string name() = 0;
    ...

struct Named {
    std::string name;
};

struct NamedPerson : Person, private Named {
    std::string name() override {
        return name;
    }
};

struct JaredPerson : Person {
    std::string name() override {
        return "Jared";
    }
};

Здесь есть база с переменной, но Джаред не наследует эту конкретную базу.

2 голосов
/ 08 мая 2020

Нет.

Наследование от класса означает, что вы включаете все его переменные-члены, переменные-члены родительского класса [s], плюс все, что содержится в вашем собственном классе.

Другими словами Кстати, дочерние классы являются надмножеством родительских классов. (за исключением пустого дочернего класса)

Даже частные члены по-прежнему там занимают место, попытка доступа к ним просто ошибка компилятора.

1 голос
/ 08 мая 2020

Ответ должен быть ясен, если вы используете полиморфизм. То есть воспользуйтесь преимуществами языковых функций, которые позволяют рассматривать объект производного типа как один из базового типа. Предположим, что Person является publi c base of PersonNamedJared, и рассмотрим следующий код.

PersonNamedJared Jared;
Person * Pointer = &Jared;
std::cout << Pointer->name << " is " << Pointer->age << " years old.";

Это верно, но как этот код мог бы работать, если PersonNamedJared не содержал name field?

Как показывает опыт, если у вас есть законная причина, чтобы производный класс был меньше, чем его базовый класс, то, вероятно, что-то не так с вашим дизайном класса.


Что касается того, может ли быть язык с этой функцией, я думаю, что это возможно, но довольно неудобно. Вы можете - на гипотетическом языке - стереть грань между членами данных и членами функций, позволив идентификатору name представлять (виртуальные) данные в базовом классе, но функцию в производных классах. Таким образом, производный класс может предоставлять функцию с именем name, заменяющую версию базового класса. Вы можете заблокировать явные ссылки на версию name базового класса * при работе с объектом производного типа. При достаточном количестве требований и запретов поле name будет недоступно в определенных объектах производного класса, следовательно, им оно не понадобится. В этом случае поле имени можно не указывать. (Однако я не знаю ни одного языка, который допускает такую ​​строгую настройку.)

С другой стороны, похоже, что такая настройка противоречит принципам наследования. Даже если бы язык позволял такую ​​настройку, я бы предпочел лучший дизайн класса.

1 голос
/ 08 мая 2020

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

В C ++ нет!

Даже если вы попытаетесь заменить член базового класса с меньшим членом в производном классе (с тем же именем), член базового класса все еще существует (к нему труднее получить доступ). Этот код продемонстрирует, что с производным классом на самом деле добавляет к размеру базы:

#include <iostream>

class A {
public:
    double q[200];
};

class B : A {
public:
    double q[100]; // Can we replace base array with a smaller one?
};

int main()
{
    std::cout << sizeof(A) << std::endl; // -> 1600 = 200 * sizeof(double)
    std::cout << sizeof(B) << std::endl; // -> 2400 ADDS 100 more doubles!
    return 0;
}
...