C++ 类及OOP编程

本文围绕C++类及面向对象编程(OOP)展开。介绍了OOP的特点,如抽象、封装、多态、继承等。阐述了C++类中数据隐藏、公共接口等概念,说明了类的定义包括声明和方法定义。还提及应用者使用类的方式,最后探讨了类的大小相关问题,包括虚函数、虚继承等情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

理论知识:C++类及OOP编程

开门见山:OOP(面向对象编程)的特点:

  1. 抽象
  2. 封装和数据隐藏
  3. 多态
  4. 继承
  5. 代码的可重用性

关于类:

C++中关于类的应用,是面对开发者的,为了保持类的稳定系,需要对【数据成员】进行数据隐藏,也就是放在private中。

原因非常简单,如果开发者都可以修改了,那么类的稳定性就会差很多。

但是为了开发者,还是有一些内容是public的,是开发者可以直接调用的

那么这个部分就叫【类方法】,也叫【公共接口的类成员】。这就叫抽象,将众多复杂问题的核心抽象出来变成函数。

以上概念众多,那么如何更好的理解呢?

乙方将【公共接口的类成员】设置好,这些接口是要面对甲方的,甲方根据需要选择,这部分的成员是public的,因为要面向甲方,甲方必须有权限进行自由的调用及使用。

那么乙方为了保护用品的稳定性,不可能将所有内容都公开,那么【公共接口的类成员】及【类方法】使用过程中调用的变量,均为private,这部分内容甲方不可见也不可调用。

以上乙方做的工作,统称为封装

封装:将实现细节放在一起并将它们与抽象分开被称为封装

数据隐藏是一种封装,将类函数定义和类声明放在不同的文件中也是一种封装。

具体关于类的内容:

类的定义分为以下两个部分

类声明:

  1. 类声明:以数据成员的方式描述数据部分,以成员函数(类方法)的方式描述公有接口
  2. 类方法定义:描述如何实现类成员函数

一般将接口(类方法)放在头文件中(类声明),并将实现(类方法的代码)放在源代码文件中(类方法定义)。

stock00.h//类声明
class Stock
{
private:
    std::string company;
    long shares;
    double share_cal;
public:
    void acquire(const std::string & co,long n,double pr);
    void buy(long num,double price);
    void sell(long num,double price);
}

stock00.cpp//类方法定义
#include"stock00.h"

void Stock::acquire(const std::string & co,long n,double pr)
{
   company = 0;//类方法是可以访问私有成员的
   .......
}

void Stock::buy(long num,double price)
{
   shares = 0;//类方法是可以访问私有成员的
   .......
}

void Stock::sell(long num,double price)
{
   share_cal = 0;//类方法是可以访问私有成员的
   .......
}

应用者如何面对:

使用成员运算符

Stock kate,joe;
kate.show();
joe.show();

用就行了,而且创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;

但是同一个类的所有对象共享同一组类方法,及每种方法只能有一个副本。

kate.show()占领一部分内存,而joe.show()占领另一部分内存。

但是执行show()代码使用的是同一段代码。

 要使用某个类,必须了解其公共接口,要编写类,必须创建其公共接口。

相关题目:

类的大小:类的大小是个问题,类的有静态关键字修饰的成员变量和函数,虚函数指针,有时候甚至涉及虚继承

 

总结:

  1. 普通的成员函数,构造和析构函数,都不会占用空间,因为非内联成员函数(non-inline member function)只会诞生一份函数实例。
  2. 静态关键字修饰的成员变量不会在类中占用空间

虚函数有虚函数指针,占用4个字节(和虚函数个数无关,所有的偏移量都存在虚函数表里面)

虚继承有虚基类指针,占有4个字节

下面我们来看看几具体的实例:

1和2两点一起进行测试:

#pragma pack(1)
class student
{
public:
    student();//构造函数(不占空间)
    int a = 0;
    static int b;//静态成员变量(不占空间)
    void show();//成员函数(不占空间)
    ~student();//析构函数(不占空间)
};
class test1:public student
{
public:
    int b;
};
    qDebug()<<"sizeof(student)"<<sizeof(student)<<endl;
    qDebug()<<"sizeof(test1)"<<sizeof(test1)<<endl;

输出:

这都很好理解,下面我们看虚函数的情况

class student
{
public:
    student();//构造函数(不占空间)
    int a = 0;
    static int b;//静态成员变量(不占空间)
    void show();//成员函数(不占空间)
    ~student();//析构函数(不占空间)

    virtual void testvirtual1();
    virtual void testvirtual2();
    virtual void testvirtual3();
};
class test1:public student
{
public:
    int b;
    void testvirtual1();
    void testvirtual2();
    void testvirtual3();
};

和上一次相比,多了4个字节,就是多了虚函数指针的大小。


多继承:

成员变量和单继承情况一样:

#pragma pack(1)
class student
{
public:
    int a = 0;
};
class test1
{
public:
    int b;
};
class test2
{
public:
    int c;
};
class test3:public test1,public test2,public student
{
public:
};

那么虚函数呢?也是一样的

#pragma pack(1)
class student
{
public:
//    int a = 0;
    virtual void testvirtual1();
    virtual void testvirtual2();
    virtual void testvirtual3();
};
class test1
{
public:
//    int b;
    virtual void testvirtual1();
    virtual void testvirtual2();
    virtual void testvirtual3();
};
class test2
{
public:
//    int c;
    virtual void testvirtual1();
    virtual void testvirtual2();
    virtual void testvirtual3();
};
class test3:public test1,public test2,public student
{
public:
//    int d;
    void testvirtual1();
    void testvirtual2();
    void testvirtual3();
};

 

我们看看多重继承下,虚函数表的情况

虚函数不覆盖的情况如上图所示,覆盖的情况如下图所示

会顺位覆盖第一个类中的内容。

所以回头再看程序,我们就会知道

student :自己的虚函数指针:4

test1:自己的虚函数指针:4

test2:自己的虚函数指针:4

test3:虚函数指针x3:12

 

最后是最复杂的情况:虚继承,因为编译器的不同,对虚继承层次的对象的内存布局,在不同编译器实现有所区别。

 

 

1:空类的大小是多少?答案:1

空类是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址

C++标准指出,不允许一个对象(当然包括类对象)的大小为0

2:

在32位系统下,sizeof(a)的值是()

int 4个字节

union U 13+4个字节, union占对齐后数据的最大字节大小,默认为13+3=4*4=16;

因为是共用体,其大小是共用体的最大成员长度

此时按照13算,4对其自然是16字节

但是,该处强制为2字节对齐,实际为13+1=2*7=14字节

color   枚举类型的实例  4字节

但是程序明确。#pragma pack(2)

所以:4+14+4 = 22

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值