我对C ++中的继承概念感到困惑,假设我们有一个名为computer的类,我们公开从计算机类继承了一个名为laptop的类。现在当我们在main函数中创建类laptop的对象时,内存中会发生什么?请解释一下。
答案 0 :(得分:11)
class Computer {
public:
Computer() { /* whatever */}
/* whatever */
};
class Laptop : public Computer {
public:
Laptop() { /* whatever */ }
/* whatever */
};
然后......
x = new Laptop();
编译器实现的目的是:
ptr = ::operator new(sizeof(Laptop))
Computer::Computer(ptr)
Laptop::Laptop(ptr)
x = ptr
我将作为练习留给读者的堆栈。
答案 1 :(得分:4)
笔记本电脑类包含自身和计算机类中定义的属性。派生类包含基类。这就是为什么Stroustrup选择术语“基类”而不是“超类”来引用继承的类。单词super意味着继承的类更大但是反过来,继承类扩展了它继承的类。编译器分配足以容纳派生类的内存块。
答案 2 :(得分:4)
我假设你想知道多态对象的内存布局。我会尝试用肉眼展示它。考虑:
class Base()
{
public:
virtual void foo();
virtual void bar();
void hello();
private:
int variable1;
};
class Derived : public Base
{
public:
virtual void foo();
virtual void bar();
void bye();
private:
float variable2;
};
(请注意:为了清楚起见,故意省略虚拟析构函数。)
内存布局如下:
/*
Base object layout:
[vftable pointer] (points to the 1st row in the virtual function table)
[int variable1 ] (from Base)
Derived object layout:
[vftable pointer] (points to the 2nd row in the virtual function table)
[int variable1 ] (inherited from Base)
[float variable2] (from Derived)
virtual function table layout:
[&Base::foo ] [&Base::bar ]
[&Derived::foo] [&Derived::bar]
*/
请注意,整个程序中只有一个用于Base和Derived的虚函数表。对于Derived的每个实例,表不会重复。相反,每个Derived实例都将一个隐藏指针保存到虚函数表的“行”中。
另请注意,hello()和bye()不会出现在vf表中,因为它们不是虚拟的。在这种情况下,正确的函数指针也可以在编译时计算出来。
此维基百科article也显示了内存布局的示例,但它更复杂,因为该示例使用多重继承。
Chip Uni使用调试器查看内存中发生的事情的想法将是一个很好的练习。
对于更高级的程序员,另一个好的练习是尝试使用结构和函数指针在C中实现多态。
答案 3 :(得分:3)
我假设笔记本电脑继承自计算机,我正在解释一般情况下会发生什么; C ++的实现细节(出于优化原因)可能与此一般解释不同。
逻辑上,Laptop类定义具有指向Computer类定义的指针。 Laptop类的实例有一个指向Laptop类定义的指针(在C ++中,很可能这只是对类方法的函数指针数组的引用)。
当笔记本电脑对象收到消息时,它首先在自己的方法表中查找相应的函数。如果不存在,则它遵循继承指针并在方法表中查找计算机类。
现在,在C ++中,大部分都发生在编译阶段,特别是我认为方法表是扁平化的,任何可以静态绑定的调用都是快捷方式。
答案 4 :(得分:2)
一个非常简单的例子可能是:
class Computer {
char manufacturer[20];
char type[10];
}
class Laptop : Computer {
int runningTime;
}
如果您现在创建一个类型为computer的对象,则将分配20 + 10 = 30个字节的内存。假设在你的系统上一个整数需要4个字节,由于制造商的继承和笔记本电脑的类型,笔记本电脑的实例将需要额外的4个字节= 34个字节。分配发挥作用的地址取决于堆的当前状态。 (实际上是内存管理等) 需要将新创建的对象分配给引用变量:
i.g。
Laptop lap = new Laptop();
答案 5 :(得分:1)
这里有一些很好的教程:
Object-Oriented Programming in C++(至少要经历“友谊与继承”)
Introduction to Object-Oriented Programming Using C++
Learning Object-Oriented Programming in C++
答案 6 :(得分:-1)
分配内存以容纳sizeof(Object)。这包括可以继承的任何原语,如int,char等。可以在堆/堆栈上。