1,
实例代码:
#include <iostream>
using namespace std;
class Top
{
protected:
int x;
public:
Top(int n)
{
x = n;
}
virtual ~Top() {}
};
class Left : virtual public Top
{
protected:
int y;
public:
Left(int m, int n) : Top(m)
{
y = n;
}
};
class Right : virtual public Top
{
protected:
int z;
public:
Right(int m, int n) : Top(m)
{
z = n;
}
};
class Bottom : public Left, public Right
{
int w;
public:
Bottom(int i, int j, int k, int m) : Top(i), Left(0, j), Right(0, k)
{
w = m;
}
};
int main()
{
Bottom b(1, 2, 3, 4);
cout << sizeof(Top) << endl;
//Top: int+虚表指针 8
cout << sizeof(Left) << endl;
//Left: 大小为Top+int+指向虚基类的指针 16
cout << sizeof(Bottom) << endl;
//Bottom: 大小为Top+Left(int + 指向虚基类的指针)+Right(int + 指向虚基类的指针)+int 28
}
(2)一个比较奇怪的地方
#include <iostream>
using namespace std;
class Top
{
public:
Top()
{
}
virtual ~Top() {}
private:
int i;
};
class Left : virtual public Top
{
public:
Left()
{
}
};
class Right : virtual public Top
{
public:
Right()
{
}
};
class Bottom : public Left, Right
{
};
class Top2
{
public:
Top2()
{
}
virtual ~Top2() {}
};
class Left2 : virtual public Top2
{
public:
Left2()
{
}
};
class Right2 : virtual public Top2
{
public:
Right2()
{
}
};
class Bottom2 : public Left2, Right2
{
};
int main()
{
cout << sizeof(Top) << endl;
cout << sizeof(Left) << endl;
//Left: Top+虚表指针 12
cout << sizeof(Bottom) << endl;
//Left: Top+虚表指针+虚表指针 16
cout << sizeof(Top2) << endl;
cout << sizeof(Left2) << endl;
//Left2: 为什么是4?
cout << sizeof(Bottom2) << endl;
//为什么 是 8?
}
(3) 多重虚继承的情况
#include <iostream>
using namespace std;
class A
{
public:
virtual void aa()
{
}
private:
char k[3];
};
class B : virtual public A
{
public:
virtual void bb()
{
}
private:
char j[3];
};
class C : virtual public B
{
public:
virtual void cc()
{
}
private:
char i[3];
};
class D : public B
{
public:
virtual void cc()
{
}
private:
char i[3];
};
int main()
{
A a;
B b;
C c;
cout<<"sizeof(A):"<<sizeof(A)<<endl;
cout<<"sizeof(B):"<<sizeof(B)<<endl;
//A+4+虚表指针 16
cout<<"sizeof(C):"<<sizeof(C)<<endl;
//B+4+续表指针 24
cout<<"sizeof(D):"<<sizeof(D)<<endl;
//B+4 20
return 0;
}
分享到:
相关推荐
此外,虚基类还允许我们使用基类的指针或引用直接指向派生类的对象,无需进行类型转换。例如,`C obj; L * ptr = &obj;`是合法的,这意味着可以通过虚基类指针访问派生类的所有公共基类成员。然而,虚基类的指针或...
虚基类的主要目的是确保只有一个实例存在,即使多个派生类通过不同的路径继承同一个基类。在声明基类时,通过在基类名前加上`virtual`关键字,可以将其设置为虚基类。这样,当一个类多继承时,所有从这个虚基类派生...
在多继承的情况下,类的对象大小可能会因为基类的贡献而增大。如果一个类从多个基类派生,且这些基类都有非空的数据成员或虚函数,那么这些基类的大小都会累加到派生类对象的大小中。需要注意的是,由于二进制布局的...
此外,虚继承的派生类在构造时需要特殊的初始化步骤,确保虚指针正确地初始化到共享基类的虚函数表。 总结来说,C++的虚函数和虚继承是实现多态性和解决多重继承问题的关键机制,它们带来了一些额外的内存开销和...
在多重继承中,如果使用了虚继承,子类的对象内存布局会包含一个虚基类表指针(vbptr),该指针指向一个虚基类表(vbtable),这个表记录了与虚基类相关的偏移量信息。虚拟菱形继承是多重虚继承中的一种特例,它需要...
这在继承体系中尤其重要,因为一个基类可能被多个派生类继承,而虚基类则确保了单一实例的存在。 C++对象模型可以分为几种不同的实现方式: 1. 简单对象模型:每个对象是一系列槽(slots),每个槽对应一个成员。...
总之,`sizeof`运算符在处理C++类时需要考虑类的成员大小、虚函数的存在以及继承关系等因素。理解这些细节对于优化内存使用和编写高效代码至关重要。在实际编程中,应时刻注意类的大小,特别是当内存管理成为一个...
- 虚基类 -> 基类对象 -> 成员对象 -> 派生类自身 复习时,应重点掌握上述知识点,特别是类、对象、指针、引用、构造与析构函数、继承、多态以及静态成员的使用。通过理解这些概念,你将能够更好地理解和编写面向...
- 多重继承:如果类从多个基类派生,编译器需要解决二义性,可能会使用虚基类来确保唯一实例。 - 虚继承:为了解决多继承中基类的多次实例化问题,引入虚基类,增加额外的指针(vptr)以指向虚基类的单一实例。 2...
在C++中,若子类的析构函数为虚函数,则当通过基类指针删除派生类对象时,会首先调用派生类的析构函数,然后调用基类的析构函数。这是因为虚析构函数确保了对象层次结构中的析构函数能按照正确的顺序被调用,避免了...
- 多继承时,情况更复杂,每个基类可能会有自己的vptr,派生类需要管理多个基类的虚函数表。 4. **C++类继承存储分配**: - 单继承时,子类对象可以直接转换为父类对象,反之则不允许,因为父类无法了解子类的...
虚继承会引入一个额外的虚基类指针,以确保每个派生类都只拥有一份虚基类的实例。这会增加一定的内存开销。 - **虚函数调用**:虚函数调用涉及到虚函数表的查找,这意味着每次调用都需要一次间接跳转。此外,还需要...
2. **多继承的基类表模型**:为了解决多继承带来的问题,每个类对象都指向一个基类表,该表包含了指向基类的指针,从而避免了派生类对象大小受多个基类的影响。 3. **C++的多继承内存模型**:C++采用了一种更复杂的...
当一个指针或引用指向基类对象,但实际调用的是派生类的成员函数,这种机制就发挥了作用。为了支持这种行为,编译器会在基类中添加一个虚函数表(Virtual Table, VTT)的指针,这个指针在每个实例化对象中都存在。虚...
15. 虚基类的目的是解决多继承带来的二义性问题,它会在构建派生类对象时仅调用一次构造函数。声明`class B: virtual public A`表明类B继承自A,并且A是虚基类。 16. 在类A的构造函数中,需要分配足够大小的内存来...
在对象模型中,子类的对象会包含基类的全部成员,这在内存中表现为子类对象的大小至少等于基类对象的大小加上子类自己添加的成员。 4. **虚函数表**:当涉及多态性时,C++使用虚函数表(VMT)来实现。每个具有虚...
在内存中,派生类对象的前部分是基类对象,接着是派生类特有的数据成员。如果基类有虚函数,派生类对象也会包含一个虚函数表指针。 - **多态性**:C++的多态主要通过虚函数实现。虚函数表使得在运行时能够动态绑定...