C++(类和对象)

news2025/1/15 22:44:15

C++中的类

C++中兼容对C语言中struct的所有用法.同时C++对struct进行了语法的升级.将struct升级成了类.

// c++中对于struct的改进:
struct Stack
{
	int* a;
	int top;
	int capacity;
}
int main()
{	
	Stack s;// 这里可以直接使用Stack进行使用,而不再需要struct关键字了
	return 0;
}

注意:

  1. 在c++中,类名就是类型,Stack就是类型,不需要加上struct关键字了

  2. 类里面可以定义函数.例如

    // c++中对于struct的改进:
    struct Stack
    {
    	int* a;
    	int top;
    	int capacity;
    
        //可以直接在类中定义函数.
        void Init()
        {
            a = NULL;
            top = 0;
    		capacity = 0;
        }
    
        void Push(int x)
        {
            .....
        }
    }
    int main()
    {	
    	Stack s;// 这里可以直接使用Stack进行使用,而不再需要struct关键字了
        s.Init(); // 直接这样调用函数.
    	return 0;
    }
    

Class的用法

访问限定符:

  • 使用public修饰的符号,在类外可以被访问
  • 使用protected和private修饰的成员在类外面不可以被访问.
  • 访问限定符的作用域 从当前位置开始,直到下一个访问限定符出现为止.如果没有出现下一个访问限定符,那么直接就修饰到结尾.
  • class的访问限定修饰符默认是private,struct默认的是public(为了和C语言适配)

虽然Class中的默认访问限定修饰符的修饰方式是private,但是最好还是将private的成员加上显性的private修饰符.

声明与定义分离

//stack.h文件
#include <iostream>
using namespace std;

class Stack
{
private:
    int *_a;
    int _top;
    int _capacity;

public:
    void Push(int x);
    void Init();
    // 注意:默认在类中定义的函数就是内联函数,前面自动会有一个inline.
    // 但是,如果函数体太长,编译器会忽略inline,将其作为普通函数处理.
    //正确的做法:
    // 长的函数声明与定义分离
    // 短的函数直接在类中定义即可.
    bool Empty()
    {
        return top == 0;
    }
};

// stack.cpp文件
#include"stack.h"

// 声明与定义分离的时候,需要使用Stack::进行修饰
void Stack::Init()
{
    _a = 0;
    _top = 0;
    _capacity = 0;

}
void Stack::Push(int x)
{
    //....
}

// main.cpp文件
#include"stack.h"
int main()
{
    return 0;
}

小技巧:

建议在私有的成员之前或者后面加上_来区分私有成员.

类的作用域

C++中花括号定义的都是域.

类的实例化

注意:在类中的成员:诸如:

class Stack
{
private:
    // 这里的成员都是声明
    int *_a;
    int _top;
    int _capacity;

public:
    void Push(int x);
    void Init();
    // 注意:默认在类中定义的函数就是内联函数,前面自动会有一个inline.
    // 但是,如果函数体太长,编译器会忽略inline,将其作为普通函数处理.
    //正确的做法:
    // 长的函数声明与定义分离
    // 短的函数直接在类中定义即可.
    bool Empty()
    {
        return top == 0;
    }
};
 // main.cpp
int main()
{
	// 此处才是定义对象
	Date d1;
	d1.Empty();
	return 0;
}

类和对象的关系:类就是设计图纸,对象就是建造出来的房子.

注意:同一个类的不同对象中的函数是一样的,但是不同对象中的成员变量是不一样的,函数会被存储到公共的区域中,一旦需要调用函数就直接去这个公共的区域中寻找即可.

类的成员变量的存储还是按照结构体内存对齐法进行对齐的.

注意:就算一个类没有任何成员,这个类的大小是1.(无成员变量的类大小是1字节)

#include"stack.h"
class B{};
int main()
{
    cout<<sizeof(B)<<endl;
    return 0;
}

在这里插入图片描述

无成员变量的类的大小是1字节,这个字节不存储任何数据,只是标识这个类存在过.

#include"stack.h"
class C{
    public:
    void f(){}
};
int main()
{
    cout<<sizeof(C)<<endl;
    return 0;
}

在这里插入图片描述

this指针

类中的成员函数的参数默认第一个是this,但是没有显示的写出来,并且在成员函数中访问成员变量时,前面也会有一个默认的this,例如: this->a.但是this指针不能显式的写实参和形参,可以在类中显式的使用.

#include<iostream>
#include"date.h"
using namespace std;
class Date
{
    private:
        int _year;
        int _month;
        int _day;
    public:
        void Init(int year,int month,int day)
        {
            this->_year=year;
            _month=month;
            _day=day;
        }
        void Print()
        {
            cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
            cout<<this->_year<<"-"<<this->_month<<"-"<<this->_day<<endl;
        }
};
int main()
{
    Date d1;
    d1.Init(2022,10,1);
    d1.Print();
    return 0;
}

那么this指针是存储在哪里的?答:在vs中,this指针是存储在栈帧中的.也就是存储在寄存器中的.

// 这段代码:会正常执行.

#include<iostream>
using namespace std;
class A{
    private:
        int a;
    public:
        void Print(){
            cout<<"A::Print()"<<endl;
        }
};
int main()
{
    A* a = nullptr;
    a->Print();
    return 0;
}

// 但是下面这样子就会运行报错.
#include<iostream>
using namespace std;
class A{
    private:
        int _a;
    public:
        void Print(){
            cout<<_a<<endl;
        }
};
int main()
{
    A* a = nullptr;
    a->Print();
    return 0;
}

默认的6个成员函数

构造函数

构造函数的主要任务并不是开空间,而是初始化对象.

特点:

  1. 函数名和类名相同
  2. 无返回值
  3. 对象实例化时自动调用
  4. 构造函数可以重载
  5. 不写构造函数,编译器会默认生成默认构造函数.这个默认的构造函数:对于内置类型不做处理,对于自定义类型,回去调用它的默认构造函数.(如果没有默认构造函数,就会调用初始化列表)C++11特意对此打了补丁,支持声明时给缺省值.
  6. 无参的构造函数和全缺省的构造函数都称为默认构造函数.并且默认构造函数只能有一个.注意:无参数构造函数,全缺省构造函数.我们没写编译器默认生成的构造函数,都可以认为是默认构造函数.但是:这三个函数不能同时存在,否则会有调用歧义.
#include<iostream>
#include"date.h"
using namespace std;
class Date
{
    private:
        int _year;
        int _month;
        int _day;
    public:
        // 构造函数
        Date(int year,int month,int day)
        {
            _year=year;
            _month=month;
            _day=day;
        }
        // 无参数构造
        Date()
        {
            _year=1;
            _month=1;
            _day=1;
        }

        void Print()
        {
            cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
        }
};
int main()
{
    // 默认调用无参数构造,注意这里不能加括号
    Date d1;
    d1.Print();

    // 主动调用有参数构造
    Date d2(2022,10,1);
    d2.Print();
    return 0;
}

注意:如果没有主动写构造函数的话,编译器会自动生成一个构造函数,但是默认生成的就是随机值.例如

#include<iostream>
#include"date.h"
using namespace std;
class Date
{
    private:
        int _year;
        int _month;
        int _day;
    public:
        void Print()
        {
            cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
        }
};
int main()
{
    
    Date d1;
    // 打印随机值
    d1.Print(); 
    return 0;
}

默认生成的构造函数:

对于自定义类型(class ,struct等),会去调用它的构造函数.

对于内置类型(int/double/指针)的成员不做处理.(例如:Date* 也是内置类型)

但是我们可以在声明的时候给成员变量赋一个缺省值.

#include<iostream>             
#include"date.h"                 
using namespace std;                 
class Date                 
{
    private:                 
    // C++11支持                 
        int _year = 1;                 
        int _month = 1;                 
        int _day = 1;                 
    public:                 
        void Print()                 
        {
            cout<<_year<<"-"<<_month<<"-"<<_day<<endl;                 
        }
};
int main()                 
{
    
    Date d1;
    d1.Print(); 
    return 0;
}
析构函数

功能:对象在销毁时,会自动调用析构函数,完成对象中的资源清理工作.

特点:

  1. 函数名是在类名之前加上~
  2. 无参数返回值类型
  3. 一个对象只能有一个析构函数.若没有显式定义,系统会自动生成默认的析构函数. 注意:析构函数不能重载
  4. 对象声明周期结束时,C++编译系统会自动调用析构函数.

默认生成析构函数的行为与默认生成构造函数相似:

  1. 内置类型成员不做处理
  2. 自定义类型成员会去调用它的析构函数.

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

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

相关文章

centos 8 中安装Docker

注&#xff1a;本次样式安装使用的是centos8 操作系统。 1、镜像下载 具体的镜像下载地址各位可以去官网下载&#xff0c;选择适合你们的下载即可&#xff01; 1、CentOS官方下载地址&#xff1a;https://vault.centos.org/ 2、阿里云开源镜像站下载&#xff1a;centos安装包…

Sui Move:基本概览一

Module (模块) Move 代码被组织成模块, 可以把一个模块看成是区块链上的一个智能合约 可以通过调用这些模块中的函数来与模块进行交互&#xff0c;可以通过事务或其他 Move 代码来实现, 事务将被发送到并由Sui区块链进行处理&#xff0c;一旦执行完成&#xff0c;结果的更改将…

1/13+2

运算符重载 myString.h #ifndef MYSTRING_H #define MYSTRING_H #include <cstring> #include <iostream> using namespace std; class myString {private:char *str; //记录c风格的字符串int size; //记录字符串的实际长度int capacity; …

GD32F470Z外部晶振不起振

亲测&#xff0c;主要的原因是因为系统配置里面选择的晶振&#xff0c;选择内部还是外部的无源晶振。 1.无源晶振 打开startup_gd32f450_470.s这个起始文件。 ​​​​​​​ ​​​​​​​ 找到SystemInit。 跳进去这个函数。 在这个函数里面最底下找到sys…

用css和html制作太极图

目录 css相关参数介绍 边距 边框 伪元素选择器 太极图案例实现、 代码 效果 css相关参数介绍 边距 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style>*{margin: 0;padding: 0;}div{width: …

【2025 Rust学习 --- 17 文本和格式化 】

字符串与文本 Rust 的主要文本类型 String、str 和 char 内容概括&#xff1a; Unicode 背景知识&#xff1f;单个 Unicode 码点的 char&#xff1f;String 类型和 str 类型都是表示拥有和借用的 Unicode 字符序列。Rust 的字符串格式化工具&#xff0c;比如 println! 宏和 …

C#中颜色的秘密

颜色的秘密: 颜色Color是一个调色板, 所有颜色都是由透明度Alpha,红Red,绿Green,蓝Blue按不同比例调色混合而成,如果不考虑透明度Alpha,颜色共有256*256*25616777216种 ColorARGB A,R,G,B都为byte型[8位],因此可以用整体的32个整数[Int32]来表示一种颜色 Color 所属命名空…

Pycharm 使用教程

一、基本配置 1. 切换Python解释器 pycharm切换解释器版本 2. pycharm虚拟环境配置 虚拟环境的目的&#xff1a;创建适用于该项目的环境&#xff0c;与系统环境隔离&#xff0c;防止污染系统环境&#xff08;包括需要的库&#xff09;虚拟环境配置存放在项目根目录下的 ven…

phpenc加密程序源码

免费扩展加密程序&#xff0c;类似于sg11加密&#xff0c;支持单个PHP&#xff08;免费&#xff09;文件以及批量PHP文件&#xff08;ZIP压缩包格式&#xff09;源码加密的保护平台&#xff0c;加密后的源码文件保持原有代码结构&#xff0c;可以跨平台运行&#xff0c;可以运行…

视频转码对画质有影响吗?视频融合平台EasyCVR支持哪些转码格式?

视频转码过程是将视频文件从一种编码格式转换为另一种格式的过程&#xff0c;这一过程在现代数字媒体中扮演着至关重要的角色。众所周知&#xff0c;视频转码不仅仅是简单的格式转换&#xff0c;它涉及多个关键参数的改变&#xff0c;例如视频编码格式、比特率、分辨率以及帧率…

LeetCode热题100(哈希篇)

题目出自Leetcode热题100&#xff1a;Leetcode热题100 文章目录 1. 两数之和思路代码CJavaPython 49. 字母异位词分组思路代码CJavaPython 128. 最长连续序列思路代码CJavaPython 总结 1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找…

python学opencv|读取图像(三十一)缩放图像的三种方法

【1】引言 前序学习进程中&#xff0c;我们至少掌握了两种方法&#xff0c;可以实现对图像实现缩放。 第一种方法是调用cv2.resize()函数实现&#xff0c;相关学习链接为&#xff1a; python学opencv|读取图像&#xff08;三&#xff09;放大和缩小图像_python opencv 读取图…

rk3568 , buildroot , qt ,使用sqlite, 动态库, 静态库

问题说明&#xff1a; 客户反馈 &#xff0c;buildroot 系统 &#xff0c;使用qt 使用sqlite &#xff0c;有报错&#xff0c;无法使用sqlite. 测试情况说明&#xff1a; 我自己测试&#xff0c;发现&#xff0c; buildroot 自己默认就是 使能了 sqlite 的。 是否解决说明&…

Windows图形界面(GUI)-QT-C/C++ - Qt图形绘制详解

公开视频 -> 链接点击跳转公开课程博客首页 -> ​​​链接点击跳转博客主页 目录 Qt绘图基础 QPainter概述 基本工作流程 绘图事件系统 paintEvent事件 重绘机制 文字绘制技术 基本文字绘制 ​编辑 高级文字效果 基本图形绘制 线条绘制 ​编辑 形状绘制 …

OpenArk64:Windows 系统分析与逆向工程工具详解

引言 在 Windows 系统的底层操作和逆向工程领域&#xff0c;OpenArk 是一款备受推崇的开源工具集。而 OpenArk64.exe 是 OpenArk 工具的 64 位版本&#xff0c;专门用于 64 位 Windows 系统。它提供了强大的功能&#xff0c;帮助用户深入分析系统内核、进程、文件、注册表等&a…

浅谈计算机网络02 | SDN控制平面

计算机网络控制平面 一、现代计算机网络控制平面概述1.1 与数据平面、管理平面的关系1.2 控制平面的发展历程 二、控制平面的关键技术剖析2.1 网络层协议2.1.1 OSPF协议2.1.2 BGP协议 2.2 SDN控制平面技术2.2.1 SDN架构与原理2.2.2 OpenFlow协议2.2.3 SDN控制器 一、现代计算机…

【C++】PP5015 [NOIP2018 普及组] 标题统计

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目背景题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示数据规模与约定 &#x1f4af;方法分析方法1&#xff1a;我的做法实…

从玩具到工业控制--51单片机的跨界传奇【2】

咱们在上一篇博客里面讲解了什么是单片机《单片机入门》&#xff0c;让大家对单片机有了初步的了解。我们今天继续讲解一些有关单片机的知识&#xff0c;顺便也讲解一下我们单片机用到的C语言知识。如果你对C语言还不太了解的话&#xff0c;可以看看博主的C语言专栏哟&#xff…

线程池面试题目集合

最近面试中总是问到ThreadPoolExecutor类相关问题&#xff0c;在此集中整理下。 问题1.ThreadPoolExecutor的关键参数是哪些&#xff0c;任务添加过程中&#xff0c;内部线程是怎样构建的&#xff1f; a)任务到达时&#xff0c;线程池数目小于核心线程数corePoolSize&#xff0…

程序员独立开发竞品分析:确定网站使用什么建站系统

要确定一个网站使用的建站系统&#xff0c;可以通过以下几种方法尝试分析&#xff1a; 查看页面源代码&#xff1a; 打开网站&#xff0c;右键点击页面并选择“查看页面源代码”。在代码中查找一些常见的建站系统标志&#xff0c;例如&#xff1a; WordPress 的迹象&#xff1a…