C++:类和对象(上)

目录

一、类的定义

二、 访问限定符

三、 实例化概念类:

类(Class)

对象(Object)

实例化(Instantiation)

四、 对象大小

五、this 指针的基本概念

this 指针的作用:

this 指针的类型:

this 指针的隐式传递:


一、类的定义

1、class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。

类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。

class 类名 Stack {//访问修饰符://成员变量;//成员函数;
};

2、为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_或者m 开头。

class Stack {
private:int top_;  // 成员变量,私有int* data_;  // 成员变量,私有public:Stack();  // 构造函数~Stack();  // 析构函数void push(int value);  // 成员函数int pop();  // 成员函数bool isEmpty() const;  // 成员函数
};

3、 C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是 struct中可以定义函数,⼀般情况下我们还是推荐用class定义类。

4、 定义在类⾯的成员函数默认为inline。

class MyClass {
public:// 这个函数在类定义内部定义,因此默认是 inlinevoid myFunction() {std::cout << "Hello, world!" << std::endl;}
};int main() {MyClass obj;obj.myFunction(); // 调用可能会被内联return 0;
}

在这个例子中,myFunction 是在 MyClass 类的定义内部声明并定义的,所以它是隐式内联的。

但是,如果你在类外部定义成员函数,则需要显式地使用 inline 关键字来请求编译器将其作为内联函数处理,尽管这仍然是一个建议而非强制要求:
 

class MyClass {
public:void myFunction();
};// 需要显式指定 inline
inline void MyClass::myFunction() {std::cout << "Hello, world!" << std::endl;
}

总结来说,C++ 中在类定义内部定义的成员函数默认为 inline 函数,这是一个方便的特性,可以提高代码的执行效率,特别是在处理小型、频繁调用的函数时。是否实际内联是由编译器决定的。

二、 访问限定符

• C++⼀种实现封装的方式,⽤类将对象的属性与方法结合在⼀块,让对象更加完善,通过访问权限选择性的将其接⼝提供给外部的用户使用。

public修饰的成员在类外可以直接被访问;protectedprivate修饰的成员在类外不能直接被访 问,protected和private是⼀样的,以后继承章节才能体现出他们的区别。

• 访问权限作用域从该访问限定符出现的位置开始直到下⼀个访问限定符出现时为⽌,如果后面没有 访问限定符,作用域就到}即类结束。

• class定义成员没有被访问限定符修饰时默认为private,struct默认为public。

• ⼀般成员变量都会被限制为private/protected,需要给别⼈使一瓶的成员函数会放为public。。

class MyClass {
private:int privateVar;  // 私有成员变量
protected:int protectedVar;  // 受保护的成员变量
public:int publicVar;  // 公共成员变量void publicMethod() {  // 公共成员函数privateVar = 10;protectedVar = 20;publicVar = 30;}void protectedMethod() {  // 受保护的成员函数// 可以访问所有类型的成员}private:void privateMethod() {  // 私有成员函数// 只能在类内部访问}
};struct MyStruct {int var1;  // 默认为 public
private:int var2;  // 私有成员变量
protected:int var3;  // 受保护的成员变量
};

总结
public 成员可以在任何地方被访问。
protected 成员可以在类的内部及其派生类中被访问。
private 成员只能在类的内部被访问。
class 中的成员默认为 private,struct 中的成员默认为 public。
通常,成员变量被限制为 private 或 protected,成员函数被设置为 public。

三、 实例化概念类:

类(Class)

类是一种用户自定义的数据类型,它描述了一组具有相同属性(成员变量)和行为(方法)的对象。类就像是一个蓝图或模板,规定了基于这个类创建的所有对象应该具有的特征和行为。但是,类本身并不占用内存中的实际空间,它只是一个模板或者说是对象的定义

对象(Object)

对象是类的一个实例。当我们使用类创建一个对象时,实际上是在内存中为该对象分配了一块空间来存储它的状态(即成员变量的值)。每个对象都有自己独立的一套成员变量副本,这意味着即使是从同一个类创建出来的不同对象,它们之间也不会相互影响。

实例化(Instantiation)

定义:实例化是根据类的定义创建具体对象的过程。
过程:
内存分配:为对象分配内存空间。
初始化:设置对象的初始状态(即成员变量的初始值)。

#include <iostream>
using namespace std;class Person {
private:string name;int age;public:// 构造函数Person(string n, int a) : name(n), age(a) {}// 方法void introduce() const {cout << "Name: " << name << ", Age: " << age << endl;}
};int main() {// 实例化一个Person对象Person person1("Alice", 30);// 调用对象的方法person1.introduce();return 0;
}

总结
类:定义了对象的结构和行为。
对象:类的具体实例,具有独立的状态和行为。
实例化:根据类的定义创建对象的过程。

四、 对象大小

成员变量的大小:每个成员变量都有自己的大小,例如 int 通常占 4 字节,char 占 1 字节,double 占 8 字节等
对齐规则:为了提高内存访问效率,编译器会对成员变量进行对齐处理。这意味着成员变量可能不会紧挨着存储,而是会有一定的填充字节。
虚函数表指针:如果类中有虚函数,那么每个对象会包含一个指向虚函数表的指针,这个指针通常占用 4 或 8 字节(取决于平台)。

#include <iostream>class MyClass {
public:char a;      // 1 byteint b;       // 4 bytesdouble c;    // 8 bytes
};int main() {std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl;return 0;
}

成员变量的大小:
char a 占 1 字节
int b 占 4 字节
double c 占 8 字节

对齐规则:
编译器通常会对成员变量进行对齐处理,以确保每个成员变量的地址是其大小的倍数。例如,int 必须对齐到 4 字节边界,double 必须对齐到 8 字节边界。
假设 MyClass 对象的布局如下:
char a 占 1 字节
填充 3 字节(使 int b 对齐到 4 字节边界)
int b 占 4 字节
double c 占 8 字节
因此,MyClass 对象的总大小为:
1 + 3 + 4 + 8 = 16 字节

如果类中包含虚函数,那么每个对象还会包含一个指向虚函数表的指针(vptr)。

#include <iostream>class MyVirtualClass {
public:virtual void foo() {}char a;      // 1 byteint b;       // 4 bytesdouble c;    // 8 bytes
};int main() {std::cout << "Size of MyVirtualClass: " << sizeof(MyVirtualClass) << " bytes" << std::endl;return 0;
}

在这种情况下,MyVirtualClass 对象的布局可能会是:

vptr 占 8 字节(假设 64 位系统)
char a 占 1 字节
填充 3 字节(使 int b 对齐到 4 字节边界)
int b 占 4 字节
double c 占 8 字节

因此,MyVirtualClass 对象的总大小为:

8 + 1 + 3 + 4 + 8 = 24 字节

成员变量的大小 是决定对象大小的主要因素。
对齐规则 可能会导致额外的填充字节。
虚函数 会增加一个指向虚函数表的指针,从而增加对象的大小。

五、this 指针的基本概念

this 指针的作用:

this 指针是一个指向当前对象的指针,它在每个非静态成员函数中都是隐式存在的。
当一个对象调用其成员函数时,this 指针会被自动传递给该成员函数,使得成员函数能够访问和操作调用该函数的对象的成员变量和成员函数。

this 指针的类型:

this 指针的类型是当前类的指针类型。例如,对于 Date 类,this 指针的类型是 Date*。

this 指针的隐式传递:

在成员函数的参数列表中,this 指针是隐式的,编译器会自动处理。你不需要在调用成员函数时显式传递 this 指针

#include <iostream>class Date {
public:// 构造函数Date() : _year(0), _month(0), _day(0) {}// 初始化函数void Init(int year, int month, int day) {_year = year;_month = month;_day = day;}// 打印函数void Print() const {std::cout << _year << "-" << _month << "-" << _day << std::endl;}private:int _year;int _month;int _day;
};int main() {Date d1, d2;// 调用Init函数初始化d1d1.Init(2023, 10, 5);// 调用Init函数初始化d2d2.Init(2024, 11, 7);// 调用Print函数打印d1d1.Print(); // 输出: 2023-10-5// 调用Print函数打印d2d2.Print(); // 输出: 2024-11-7return 0;
}

4 、C++和C语言实现Stack对比

在C语言和C++语言中实现栈(Stack)时,虽然它们的底层逻辑相似,都是遵循后进先出的原则,但是由于两种语言特性的不同,实现的方式和风格上存在显著差异。

在C语言中,通常使用结构体(struct)来定义栈的数据结构,并通过一组函数来操作这个结构体。例如,定义一个简单的整数栈可能需要如下步骤:

定义一个结构体来表示栈,包括一个数组或指针用于存储元素,以及一个变量记录栈顶的位置。
编写一系列函数(如push, pop, isEmpty等),这些函数接受指向栈结构体的指针作为参数,以执行相应的操作。
在这种实现中,数据和操作数据的方法是分离的,客户端代码可以直接访问结构体中的字段。这意味着没有访问控制,任何人都可以随意修改结构体内部的状态,这可能会导致程序不稳定。

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}
void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{assert(ps);
if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity * 
sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}
STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{assert(ps);
return ps->top;
}
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d\n", STTop(&s));STPop(&s);}STDestroy(&s);return 0;
}

C++语言实现
而在C++中,可以通过定义一个类(class)来实现栈,这种方式利用了封装这一面向对象编程的核心概念:

类中包含了私有成员(private members),用于存储栈的数据和状态,外部无法直接访问这些成员。
公共成员函数(public member functions)提供了对外部访问的接口,如push, pop, isEmpty等方法,这些方法内部实现了对私有数据的操作。
构造函数可以初始化栈,而析构函数可以清理资源,确保栈在生命周期结束时正确释放内存。
通过这种方式,C++的实现不仅隐藏了数据的具体实现细节,还保护了数据不被外部代码随意修改,从而提高了代码的安全性和可维护性。此外,C++中的成员函数自动接收一个this指针,该指针指向调用该函数的对象实例,这使得成员函数的调用更加简洁方便。

默认参数:C++支持函数参数的默认值,这在某些情况下可以简化函数调用,提高代码的灵活性。
类型别名:虽然C++也支持typedef关键字,但更推荐使用using关键字来创建类型别名,这在C语言中是不可用的。
模板:C++的模板功能允许创建泛型栈,即可以在编译时指定栈中存储的元素类型,而无需为每种类型编写单独的栈实现
 

#include <iostream>
#include <stdexcept>class Stack {
private:static const int MAX_SIZE = 100;int data[MAX_SIZE];int top;public:Stack() : top(-1) {}bool is_empty() const {return top == -1;}void push(int value) {if (top >= MAX_SIZE - 1) {throw std::overflow_error("Stack Overflow");}data[++top] = value;}int pop() {if (is_empty()) {throw std::underflow_error("Stack Underflow");}return data[top--];}
};int main() {Stack s;s.push(1);s.push(2);s.push(3);while (!s.is_empty()) {std::cout << s.pop() << " ";}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/15781.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

如何在vscode 中打开新文件不覆盖上一个窗口

在 VSCode 中&#xff0c;如果你单击文件时出现了覆盖Tab的情况&#xff0c;这通常是因为VSCode默认开启了预览模式。在预览模式下&#xff0c;单击新文件会覆盖当前预览的文件Tab。为了解决这个问题&#xff0c;你可以按照以下步骤进行操作 1.打开VSCode&#xff1a;启动你的…

Linux篇(权限管理命令)

目录 一、权限概述 1. 什么是权限 2. 为什么要设置权限 3. Linux中的权限类别 4. Linux中文件所有者 4.1. 所有者分类 4.2. 所有者的表示方法 属主权限 属组权限 其他权限 root用户&#xff08;超级管理员&#xff09; 二、普通权限管理 1. ls查看文件权限 2. 文件…

冲压车间如何开展六西格玛管理培训

面对日益严苛的客户要求与成本控制挑战&#xff0c;传统的管理模式已难以满足高质量发展的需求。此时&#xff0c;六西格玛管理以其严谨的数据驱动、持续改进的理念&#xff0c;成为众多企业转型升级的有力工具。本文&#xff0c;天行健企业管理咨询公司将深入探讨冲压车间如何…

基于微信小程序的平安驾校预约平台的设计与实现(源码+LW++远程调试+代码讲解等)

摘 要 互联网发展至今&#xff0c;广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱&#xff0c;出错率高&#xff0c;信息安全性差&#xff0c;劳动强度大&#xff0c;费时费力…

插入排序(sort)C++

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 时间限制&#xff1a;C/C/Rust/Pascal 1秒&#xff0c;其他语言2秒 空间限制&#xff1a;C/C/Rust/Pascal 512 M&#xff0c;其他语言1024 M 64bit IO Format: %lld 题目描述 插入排序是一种…

卷积、频域乘积和矩阵向量乘积三种形式之间的等价关系与转换

线性移不变系统 线性移不变系统&#xff08;Linear Time-Invariant System, LTI系统&#xff09;同时满足线性和时不变性两个条件。 线性&#xff1a;如果输入信号的加权和通过系统后&#xff0c;输出是这些输入信号单独通过系统后的输出的相同加权和&#xff0c;那么该系统就…

15分钟学 Go 第 53 天 :社区资源与学习材料

第53天&#xff1a;社区资源与学习材料 目标 了解Go语言官方资源掌握社区重要学习平台学会利用开源项目学习构建个人知识体系 一、Go语言官方资源汇总 资源类型网址说明Go官网golang.org官方文档、下载、教程Go Blogblog.golang.org技术博客、最新特性介绍Go Playgroundpla…

「QT」文件类 之 QIODevice 输入输出设备类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「Win」Windows程序设计「IDE」集成开发环境「UG/NX」BlockUI集合「C/C」C/C程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「UG/NX」NX定制…

timescale使用例子 - 纽约出租车

一、资料使用 在timescale的官方网站的“教程”菜单中&#xff0c;有几个不同业务场景的例子&#xff0c;其中就有运输行业的例子。我访问中文站点的时候&#xff0c;关于教程的几个步骤内容刷不出来&#xff0c;所以还是建议访问英文站点。 https://docs.timescale.com/tuto…

树(二叉查找树、平衡二叉树、红黑树)

树&#xff08;二叉树、二叉查找树、平衡二叉树、红黑树&#xff09; 二叉查找树&#xff08;二叉排序树、二叉搜索树&#xff09;添加元素查找元素遍历弊端 平衡二叉树旋转机制&#xff1a;左旋旋转机制&#xff1a;右旋需要旋转的四种情况1. 左左&#xff1a;一次右旋2. 左右…

医疗器械包装运输试验之抗压试验的条件选取及方法和设备的要求

医疗器械包装运输试验之抗压试验的试验目的&#xff1a; 抗压试验通常用来评估产品在承受外界压力时&#xff0c;包装对内装物样品的保护能力。试验通常模拟产品在运输流通过程中可能遇到的压力环境。通过试验&#xff0c;可以验证包装对内装物的保护能力、包装结构的完整性、…

C++内存池实现

1.内存池概念 内存池就和其他的池数据&#xff08;如线程池&#xff09;结构类似&#xff0c;由程序维护一个“池”结构来管理程序使用的内存&#xff0c;然后根据需要从内存池中申请使用内存或者向内存池中释放内存&#xff0c;来达到高效管理内存的目的。 在一般的内存管理的…

数据结构-二叉树

一.二叉树的定义 二叉树有左右儿子之分 完美二叉树&#xff08;满二叉树&#xff09;除了最下面的没有儿子其他结点都有两个儿子&#xff0c;叶节点比较齐的&#xff0c;完全二叉树不是满二叉数允许缺失最后的结点 满二叉树可以达到2^k-1 边的总数节点数-1 二.二叉树的存储结构…

OKR制定指南

Goal Crafting 目标制定是最基本的领导活动之一。组织绩效和团队成长依赖于精心制定的目标。没有良好的目标制定练习&#xff0c;团队可能只关注眼前的事务&#xff0c;解决看似可以快速解决的问题。良好的目标制定迫使你不忽视或推迟那些需要新思维方式、合作或克服困难的问题…

详细分析Java中FilterChain过滤器的基本知识

目录 前言1. 基本知识2. Demo 前言 基本的Java知识推荐阅读&#xff1a; java框架 零基础从入门到精通的学习路线 附开源项目面经等&#xff08;超全&#xff09;【Java项目】实战CRUD的功能整理&#xff08;持续更新&#xff09; 从实战中学习&#xff1a; 常用在一些重复代…

TableGPT2-7B:用于表格数据分析的大规模解码器模型

TableGPT2-7B 是浙江大学开发的最先进的大规模解码器模型&#xff0c;专为涉及表格数据的数据密集型任务而设计。该模型以 Qwen2.5 架构为基础&#xff0c;包括针对表格数据的专用编码&#xff0c;其中独特的语义编码器可从行、列和整个表格中获取洞察力。 主要特点和功能 Ta…

SQL面试题——抖音SQL面试题 主播播出时长

主播播出时长 现有如下数据,主播id、房间号、播出的批次号,每个批次号进出房间的时间戳、分区时间: 每一次直播都有一个上播和下播,每个房间里,同一个批次号会有两条数据,分别记录了上播和下播时间,求每个主播的播出时长? 通过上面的数据,可以清晰的看出,同一个批次…

数字信号处理Python示例(14)生成锯齿波和三角波

文章目录 前言一、锯齿波和三角波二、生成锯齿波和三角波的Python代码三、仿真结果及分析写在后面的话 前言 因其独特的数学特性和物理表现&#xff0c;在工程和技术领域扮演着重要角色。这是生成非正弦信号的几个Python示例的其中一个&#xff0c;生成三角波与锯齿波&#xf…

HBase理论_HBase架构组件介绍

近来有些空闲时间&#xff0c;正好最近也在开发HBase相关内容&#xff0c;借此整理一下学习和对HBase组件的架构的记录和个人感受&#xff0c;付出了老夫不少心血啊&#xff0c;主要介绍的就是HBase的架构设计以及我的拓展内容。内容如有不当或有其他理解 matirx70163.com HB…

前端快速上手(一):HTML

目录 1. HTML 基础 1.1 HTML 标签 1.2 标签的结构关系 2. HTML 常见标签 2.1 标题标签: h1 - h6 2.2 段落标签: p 2.3 换行标签: br 2.4 图片标签: img 2.5 超链接: a 标签 2.5.1 外部链接 2.5.2 内部链接 2.5.3 文件资源链接 2.5.4 空链接 2.6 表格标签 2.7 表单…