C++ 类与对象(三)—空类、友元函数、类大小

空类

默认添加哪些函数

1)  Empty(); // 缺省构造函数//
2)  Empty( const Empty& ); // 拷贝构造函数//
3)  ~Empty(); // 析构函数//
4)  Empty& operator=( const Empty& ); // 赋值运算符//

空类大小

  1. C++空类大小不为0,不同编译器设置不一样,VS设置为1
  2. C++标准指出不允许一个对象大小为0,不同对象不能有相同地址
  3. 带有虚函数的C++类大小不为1,因为每一个对象会有一个vptr指向虚函数表,具体大小根据指针大小确定。
  4. 编译器自动为空类分配一个字节大小,这样就可以保证每个实例均有独一无二的内存地址
  5. 当空类作为基类的时候,大小就优化为0了,子类大小就是子类本身大小,这就是空白基类最优化
空类大小为1字节
class A {};
int main(){
  cout<<sizeof(A)<<endl;// 输出 1;
  A a; 
  cout<<sizeof(a)<<endl;// 输出 1;
  return 0;
}

虚函数类对象有一个虚表指针_vptr
class A { virtual void Fun(){} };
int main(){
  cout<<sizeof(A)<<endl;// 输出 4(32位机器)/8(64位机器);
  A a; 
  cout<<sizeof(a)<<endl;// 输出 4(32位机器)/8(64位机器);
  return 0;
}

静态成员放在静态存储区,不占用类大小,普通函数也是
class A { static int a; };
int main(){
  cout<<sizeof(A)<<endl;// 输出 1;
  A a; 
  cout<<sizeof(a)<<endl;// 输出 1;
  return 0;
}

如何设计一个计算仅单个子类的对象个数

  1. 添加一个static变量count作为计数器
  2. 类定义结束之后初始化count
  3. 构造函数中对count+1
  4. 设计拷贝构造函数,count+1
  5. 设计赋值构造函数,count+1
  6. 析构函数中count–

友元

什么是友元

友元用于在类之间共享私有成员,一个类将另一个类声明为友元,这样就可以让友元类访问私有成员。友元可以是一个函数、一个类或者一个成员函数(一个类将另一个类的成员函数声明为其友元)。

class MyClass {
private:
  int private_member;
  friend void FriendFunction(MyClass& myclass);
};

void FriendFunction(MyClass& myclass) {
  myclass.private_member = 42; // 可以访问 MyClass 的私有成员
}

为什么友元必须在类内部声明

否则编译器无法识别它是友元函数。

使用友元时应该注意

  • 友元关系不能被继承
  • 友元关系是单向的,不具有交换性。
  • 不具有传递性。

类的对象存储空间

  • 非静态成员的数据类型大小之和
  • 编译加入的额外成员变量(比如指向虚函数表的指针)
  • 内存对齐另外分配的空间大小,类内的数据也是需要进行内存对齐操作的
  • 当该类是某类的派生类,那么派生类继承的基类部分的数据成员也会存放在派生类空间中,也会对派生类进行扩展

类的数据成员和成员函数内存分布

代码来源阿秀的学习笔记

#include <iostream>
using namespace std;

class Person
{
public:
    Person()
    {
        this->age = 23;
    }
    void printAge()
    {
        cout << this->age <<endl;
    }
    ~Person(){}
public:
    int age;
};

int main()
{
    Person p;
    cout << "对象地址:"<< &p <<endl;
    cout << "age地址:"<< &(p.age) <<endl;
    cout << "对象大小:"<< sizeof(p) <<endl;
    cout << "age大小:"<< sizeof(p.age) <<endl;
    return 0;
}
//输出结果
//对象地址:0x7fffec0f15a8
//age地址:0x7fffec0f15a8
//对象大小:4
//age大小:4

  • 成员函数不占用对象内存,因为被放在代码区
  • 静态函数也是放在代码区的,静态成员函数与一般成员函数唯一区别就是没有this指针,因此不能访问非静态数据成员。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值