C++知识点复习 ---- 对象模型分析

本文深入探讨了C++中的类与结构体的内存布局,指出类在内存中可视为变量集合,成员函数与成员变量分开存放。成员变量遵循内存对齐规则,而成员函数位于代码段,通过对象地址隐式传递。继承方面,子类是父类成员与新成员的叠加。多态通过虚函数表实现,每个对象包含指向虚函数表的指针,但调用效率较低。
摘要由CSDN通过智能技术生成

1.回归本质

class是一种特殊的struct:
在内存中class依旧可以看做变量的集合
class与struct遵循相同的内存对齐规则
class中的成员函数与成员变量是分开存放的
每个对象由独立的成员变量
所有对象共享类中的成员函数

对象内存布局示例:

#include <iostream>
#include <string>
using namespace std;
class A
{
    int i;
    int j;
    char c;
    double d;
public:
    void print()
    {
	cout << "i = " << i << ","
	 << "j = " << j <<  ","
	 << "c = " << c <<  ","
	 << "d = " << d << endl;
    }
};
struct B
{
    int i;
    int j;
    char c;
    double d;
};
int main()
{
    A a;
    cout << "sizeof(A) = " << sizeof(A) << endl;//4+4+4+8 20bytes
    cout << "sizeof(a) = " << sizeof(a) << endl;  
    cout << "sizeof(B) = " << sizeof(B) << endl;//4+4+4+8 20bytes
    a.print();
    B* p = reinterpret_cast<B*>(&a);
    p->i = 100;
    p->j = 200;
    p->c = 'C';
    p->d = 3.14;
    a.print();
    return 0;
}
运行结果
sizeof(A) = 20  //C++对象中不包含成员函数
sizeof(a) = 20
sizeof(B) = 20
i = 4197456,j = 0,c =  ,d = 6.95323e-310
i = 100,j = 200,c = C,d = 3.14
  • 类中的成员变量:
    运行时的对象退化为结构体的形式:
    所有成员变量在内存中依次排布
    成员变量间可能存在内存间隙
    可以通过内存地址直接访问成员变量
    访问权限关键字在运行时失效
  • 类中的成员函数:
    类中的成员函数位于代码段中
    调用成员函数时对象地址作为参数隐式传递
    成员函数通过对象地址访问成员变量
    C++语法规则隐藏了对象地址的传递过程
#include <iostream>
#include <string>
using namespace std;
class Demo
{
    int mi;
    int mj;
public:
    Demo(int i, int j)
    {
        mi = i;
        mj = j;
    }
    
    int getI()
    {
        return mi;
    }   
    int getJ()
    {
        return mj;
    } 
    int add(int value)
    {
        return mi + mj + value;
    }
};
int main()
{
    Demo d(1, 2);
    cout << "sizeof(d) = " << sizeof(d) << endl; //8 bytes
    cout << "d.getI() = " << d.getI() << endl;   //1
    cout << "d.getJ() = " << d.getJ() << endl;   //2
    cout << "d.add(3) = " << d.add(3) << endl;   //6
    return 0;
}

可以使用C语言的方式来改写

小结:
C++中的类对象在内存布局上与结构体相同
成员变量和成员函数在内存中分开存放
访问权限关键字在运行时失效
调用成员函数时对象地址作为参数隐式传递

2.继承对象模型

在C++编译器内部类可以理解为结构体
子类是由父类成员叠加子类新成员得到的
drived :Demo --> int mi,int mj, int mk;
Demo --> int mi,int mj;

继承对象模型示例:

#include <iostream>
#include <string>
using namespace std;
class Demo
{
protected:
    int mi;
    int mj;
};
class Derived : public Demo
{
    int mk;
public:
    Derived(int i, int j, int k) 
    {
		mi = i;
		mj = j;
		mk = k;
    }
    void print()
    {
	cout << "mi = " << mi << ","
  	     << "mj = " << mj << ","
	     << "mk = " << mk << endl;
    }
};
struct Test
{
    int mi;
    int mj;
    int mk;
};
int main()
{
    cout << "sizeof(Demo) = " << sizeof(Demo) << endl;       //8
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl; //12
    Derived d(1,2,3);
    Test* p = reinterpret_cast<Test*>(&d);
    cout << "Before changing..." << endl;
    d.print();
    p->mi = 10;
    p->mj = 20;
    p->mk = 30;
 
    cout << "After changing..." << endl;
    d.print();
    return 0;
}
运行结果
sizeof(Demo) = 8
sizeof(Derived) = 12
Before changing...
mi = 1,mj = 2,mk = 3
After changing...
mi = 10,mj = 20,mk = 30

3.多态对象模型

C++多态的实现原理:

  • 当类中声明虚函数时,编译器会在类中生成一个虚函数表
  • 虚函数表是一个存储成员函数地址的数据结构
  • 虚函数表是由编译器自动生成与维护的
  • virtual成员函数会被编译器放入虚函数表中
  • 存在虚函数时,每个对象中都有一个指向虚函数表的指针
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    调用效率对比: 虚函数 < 普通成员函数

多态本质分析示例:

#include <iostream>
#include <string>
using namespace std;
class Demo
{
protected:
    int mi;
    int mj;
public:
    virtual void print() //声明为虚函数
    {
	cout << "mi = " << mi << ","
  	     << "mj = " << mj << endl;
    }
};
class Derived : public Demo
{
    int mk;
public:
    Derived(int i, int j, int k) 
    {
	mi = i;
	mj = j;
	mk = k;
    }
    void print()
    {
	cout << "mi = " << mi << ","
  	     << "mj = " << mj << ","
	     << "mk = " << mk << endl;
    }
};
struct Test
{
    void* p; //指向虚函数表的指针放在最开始的四个字节处
    int mi;
    int mj;
    int mk;
};
int main()
{
    cout << "sizeof(Demo) = " << sizeof(Demo) << endl;      
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl; 
    Derived d(1,2,3);
    Test* p = reinterpret_cast<Test*>(&d);
    cout << "Before changing..." << endl;
    d.print();
    p->mi = 10;
    p->mj = 20;
    p->mk = 30;
    cout << "After changing..." << endl;
    d.print();
    return 0;
}
运行结果
sizeof(Demo) = 12 //多出来的4个字节是虚函数指针成员变量
sizeof(Derived) = 16
Before changing...
mi = 1,mj = 2,mk = 3
After changing...
mi = 10,mj = 20,mk = 30

可以使用C语言来实现C++多态

小结
继承的本质就是父子间成员变量的叠加
C++中的多态是通过虚函数表实现的
虚函数表是由编译器自动生成与维护的
虚函数的调用效率低于普通成员函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值