C++类大小和静态成员/方法

类大小计算

  • 空类的大小为1字节
  • 一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的
  • 字节对齐的问题。与C语言一致
  • 没有继承的时候,存在虚函数则需要加上虚指针vptr(+4个字节),如果有多个也只需要加上一个,因为只有一个虚指针。
  • 虚基类指针:如果是虚继承,则子类的大小为:虚基类的大小 + 4个字节(用来存放指向虚基对象的指针)+子类新增成员的大小。
示例
#include <iostream>

using namespace std;

/**
 * 8=4(x)+4 (vptr)
 */
class A {
public:
    int x;

    virtual void func() {

    }
};

/**
 * 16=4(x)+4 (vptr)+4(y)+4(vbPtr)
 */
class B : virtual public A {
public:
    int y;

    virtual void funcB() {

    }
};


class B1 : virtual public A {
public:
    int z;

    virtual void funcB1() {

    }
};

/**
 * 16=4(x)+4 (vptr)+4(y)+4(B vbPtr)+4(A vbptr)+4(m)
 */
class C : virtual public B {
    int m;

    virtual void funcC() {

    }
};

/**
 * 16=4(x)+4 (vptr)+4(y)+4(B vbPtr)+4(A vbptr)+4(m)+4(z)+4(B1 vbptr)
 */
class D : public B, public B1 {
    int n;

    virtual void funcD() {

    }
};

int main() {
    A a;
    B b;
    C c;
    D d;
    cout << "sizeof(A)=" << sizeof(a) << endl;
    cout << "sizeof(B)=" << sizeof(b) << endl;
    cout << "sizeof(C)=" << sizeof(c) << endl;
    cout << "sizeof(D)=" << sizeof(d) << endl;
    return 0;
}

运行结果:

sizeof(A)=8
sizeof(B)=16
sizeof(C)=24
sizeof(D)=28
  • sizeof(A):x的大小,存在虚函数则有vptr
  • sizeof(B):x的大小,y的大小,存在虚函数则有vptr;虚继承,则还存在指向虚基类指针。
  • sizeof(C):x的大小,y的大小,m的大小,存在虚函数则有vptr;虚继承,则还存在指向虚基类指针。而基类也是虚继承,基类中也有一个指向虚基类指针。
  • sizeof(D)

静态成员变量

  • 静态变量必须在外部定义和赋值
    • a 不能在 main() 函数中定义
    • b 不能在类的构造函数中定义
  • 必须要定义静态变量,否则该变量没有内存空间(类中只是申明)
  • 类本身可以直接调用静态变量
  • 静态变量依旧符合public、private、protect特性
示例
  • 声明
//C.h
class C {
private:
    int a;
public:
    static int b;
};
  • 定义
//C.cpp
#include "C.h"
int C::b=10;
  • 使用
int main() {
    cout<<C::b<<endl;
    C::b=100;
    cout<<C::b<<endl;
    return 0;
}

静态方法

  • 静态方法可以被类直接调用,但是同静态变量一样符合public、private、protect特性
  • 静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。
  • 静态成员函数不可以同时声明为 virtual或后缀const 函数。因为virtual就是用来区分是哪个对象调用了他,与静态方法矛盾。而后缀const是用来修饰this指针的,静态变量中不包含this指针。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术碎碎念

python3 入门 (四) 类与继承

Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法。...

39112
来自专栏深度学习思考者

Python学习(三) 八大排序算法的实现(下)

本文Python实现了插入排序、基数排序、希尔排序、冒泡排序、快速排序、直接选择排序、堆排序、归并排序的后面四种。 上篇:Python学习(三) 八大排序算...

24210
来自专栏Android干货

Python正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过...

1372
来自专栏Java帮帮-微信公众号-技术文章全总结

07.Java变量类型

07.Java变量类型 Java 变量类型 在Java语言中,所有的变量在使用前必须声明。声明变量的基本格式如下: ? 格式说明:type为Java数据类型。i...

3877
来自专栏开发与安全

从零开始学C++之构造函数与析构函数(二):初始化列表(const和引用成员)、拷贝构造函数

一、构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 构造函数的执行分为两个阶段 初始化段 普通计算段 (一)、对象成员及其初始化 #inclu...

2670
来自专栏PHP在线

PHP字符串和数组操作函数

str_split() 函数把字符串分割到数组中。 stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。 stripcslas...

3927
来自专栏吾爱乐享

java之学习int和String的相互转换

841
来自专栏黑泽君的专栏

final关键字、多态、抽象类、接口的小复习

--------------------------------------- 1:final关键字可以干什么?有什么特点?   最终的意思。可以修饰类,方法...

952
来自专栏WindCoder

在数组中查找次大值,并与最后一个元素交换—C语言

1781
来自专栏Jed的技术阶梯

详解 final 修饰符

被 final 修饰的实例变量必须显示的指定初始值,而且只能在以下3个位置指定初始值:

1514

扫码关注云+社区

领取腾讯云代金券