Может ли чрезмерно глубокая иерархия классов C ++ вызвать переполнение стека? - PullRequest
3 голосов
/ 18 января 2012

Предположим, у меня есть программа на C ++, которая имеет чрезмерно глубокое наследование следующим образом:

using namespace std;

class AbstractParentGeneration0 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

class AbstractParentGeneration1: virtual public AbstractParentGeneration0 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

.
.
.

class AbstractParentGeneration999999999: virtual public AbstractParentGeneration999999998 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

class ChildGeneration: public AbstractParentGeneration999999999 {
    private:
      ...
    protected:
      ...
    public:
      returnVal funcName(void) { ... };
};

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

Нет ли опасности переполнения стека при вызове высшего абстрактного класса?

Какие стратегии (кроме «байтов ulimit -s» или свертывания абстрактной иерархии)программисты C ++ используют для работы в пределах системы?

Есть ли способ сгладить глубокую вертикальную иерархию наследования во многих хост-системах с помощью RPC?

Некоторые люди разрабатывают свой собственный механизм стека вызовов?

Существует ли такая вещь, как стек вызовов распределенной сети / кластера?

Ответы [ 5 ]

6 голосов
/ 18 января 2012

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

Общий способ решить эту проблему - перестать генерировать код, подобный этому. Не запекайте такие данные в среду выполнения. Вместо этого это должен быть некоторый формат файла, который загружается и анализируется в иерархию класса экземпляров , а не самих классов.

5 голосов
/ 18 января 2012

Нет ли опасности переполнения стека при вызове верхнего абстрактного класса?

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

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

Какие стратегии (кроме ulimit -a или свертывания абстрактной иерархии) используют программисты C ++ для работы в пределах системы?

Лично я склонен вообще избегать наследования (за исключением абстрактных интерфейсов и случаев, когда мне лень аккуратно инкапсулировать вещи).

В этом случае я мог бы предложить иерархию объектов во время выполнения, возможно, используя указатели на функции, чтобы придать аналогичное поведение виртуальным функциям; единственным ограничением будет память, необходимая для их хранения. Это не так элегантно, как использование системы типов для представления ваших категорий, но с меньшей вероятностью столкнется с ограничениями реализации.

2 голосов
/ 18 января 2012

Чтобы ответить на ваш конкретный вопрос, нет не будет опасности переполнения стека во время выполнения при вызове абстрактного виртуального метода верхнего уровня.Большинство реализаций C ++ имеют запись указателя vtable в экземпляре объекта, которая указывает непосредственно на соответствующую функцию реализации.

Если вам интересно, как это работает, я рекомендую вам написать такую ​​программу с несколькими уровнямииерархии и загрузите отладчик уровня сборки, который показывает, что на самом деле происходит.

1 голос
/ 19 января 2012

Попробуйте и убедитесь сами;)

template <int i>
class oferflowMe: public overflowMe<i-1>{
    ....
};

template <>
class oferflowMe<1>{
    ....
};
0 голосов
/ 19 января 2012

Не в этом простом случае.Однако, если у вас есть несколько виртуальных наследований, то некоторые компиляторы будут использовать «корректоры», чтобы исправить this.Эти небольшие функции окажутся в вашем стеке вызовов.

...