假设我有一个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 bytes”或者崩溃了 抽象层次结构)C ++程序员用来在其中工作 系统边界?
是否有办法在整个过程中展平深层垂直继承层次结构 许多主机系统通过RPC?
有些人设计自己的调用堆栈机制吗?
是否存在分布式网络/集群调用堆栈这样的事情?
答案 0 :(得分:6)
很可能,这会违反编译器的一些内部约束。如果出现问题,您将看不到运行时。
解决此问题的一般方法是停止生成这样的代码。不要将这种数据烘焙到运行时。相反,这应该是一些文件格式,它被加载并解析为类实例的层次结构,而不是类本身。
答案 1 :(得分:5)
肯定有。每个构造函数和析构函数都将调用父类中的对应项,一直到层次结构,生成一个非常深的调用堆栈。调用顶级抽象类时是否存在堆栈溢出危险?
如果它在构造中存活,那么调用虚函数就可以了 - 这只是对最终覆盖的单个函数调用。
C ++程序员使用什么策略(除了ulimit -a或折叠抽象层次结构)在系统边界内工作?
就个人而言,我倾向于完全避免继承(除了抽象接口,以及我懒得很好地封装东西的情况)。
在这种情况下,我可能会建议对象的运行时层次结构,可能使用函数指针来为虚函数提供类似的行为;唯一的限制是存储它们所需的内存。它不像使用类型系统来表示您的类别那样优雅,但不太可能遇到实现限制。
答案 2 :(得分:2)
要回答您的具体问题, no 在调用顶级抽象虚拟方法时,运行时不存在堆栈溢出的危险。大多数C ++实现都会在对象实例中有一个vtable指针条目,它直接指向适当的实现函数。
如果您对这是如何工作感到好奇,我建议您编写一个具有几个层次结构的程序,并加载一个程序集级调试器,向您显示实际情况。
答案 3 :(得分:1)
试试并亲自看看;)
template <int i>
class oferflowMe: public overflowMe<i-1>{
....
};
template <>
class oferflowMe<1>{
....
};
答案 4 :(得分:0)
不是在这个简单的情况下。但是,如果您有多个虚拟继承,那么一些编译器将使用“adjustor thunks”来修复this
。这些小功能将最终出现在你的调用堆栈中。