C++入门浅谈之类和对象

目录
  • 一、面向过程vs面向对象
  • 二、类的限定符及封装
  • 三、类的实例化
  • 四、this指针
  • 五、默认成员函数
    • 1. 构造函数
    • 2. 析构函数
    • 3. 拷贝函数
    • 4. 赋值运算符重载
  • 总结

一、面向过程vs面向对象

C语言面向过程,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题

C++是基于面向对象,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成,C++不是纯面向对象的语言,C++既有面向过程,也有面向对象可以混合编程。C语言面向过程,数据和方法是分离的。CPP面向对象,数据和方法是封装在一起的,如struct里即可用存数据也可以调用方法(函数)

struct ListNodeCPP{
	int val;
	ListNodeCPP* next;
};
int main(){
	//struct ListNodeCPP n1; 就不需要这样调用了
	ListNodeCPP n1;
}

所以这里的struct已经不仅仅是结构体,在cpp中已经升级成了类名

二、类的限定符及封装

类包括成员变量和成员函数

下图为类的访问限定符及封装

Warning:

在class中,如果不写访问限定符默认是私有

在struct中,如果不写访问限定符默认是公有

class类中的private里的成员变量前面都会加个下划线因为在函数复制时更加容易区分

面向对象的三大特性:封装、继承、多态

本节只介绍封装,封装是将数据和操作数据进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互

封装本质上是一种管理,类似兵马俑,如果什么都不管兵马俑就会被随意破坏那么我们首先建一座房子把兵马俑给封装起来。
但是我们不能全部封装起来,所以开放了搜票通道,买了门票的可以进去参观。类也是一样,我们使用类数据和方法都封装一下。

不想给别人看的,我们使用proteced/private把成员封装起来。开放一些共有的成员函数对成员合理的访问。所以封装本质上是一种管理

Warning:在类中private域声明的变量仅仅是声明,但是没有开空间,我们只有在实例化的时候才算是定义,public域下亦是如此。

总结就是定义是开空间,在实例化后才是定义,class里只是声明

三、类的实例化

用类类型创建对象的过程,称为类的实例化

1.类限定了有哪些成员,定义出的一个类并没有分实际的内存空间来存储它

2.一个类可以实例化多个对象,实例化出的对象占用实际的物理空间,存储类成员变量

3.类实例化出对象就像现实中造车,类是车的设计图,只负责设计需要什么东西,但并没有实体,同样类也只是个设计,实例化出的对象才能实际存储数据,占用物理空间

上图这个只算class里变量的大小,因此只保存成员变量,成员函数存放在公共的代码段

那么定义一个空类呢?

class Cpp{}

那么sizeof的大小为1 , 而不是0,因为如果一个类没有成员,那么他的对象需要给1byte进行占位
标识对象存在,这1个byte不存储有效数据

四、this指针

C++编译器给每个非静态成员函数增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中,所以成员变量的操作都是通过该指针去访问

下面的代码为编译器处理成员函数的this指针,也可以不写那么编译器会自动传隐含的this指针

class Date{
public:
    void date(int year, int month, int day){
        this->_year = year;
        this->_month = month;
        this->_day = day;
    }

    void Print(){
        cout << _year << "/" << _month << "/" << _day <<endl;
    }
private:
    int _year;
    int _month;
    int _day;
};

this指针特性:

1.this指针的类型:类类型* const

2.只能在成员函数的内部使用

3.this指针本质上是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针

4.this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传第,不需要用户传递

五、默认成员函数

上图为默认的成员函数,那么如果定义了一个class而里面什么都不写的话,仍会自动生成上面6个默认成员函数

1. 构造函数

我们首先要介绍的就是构造函数,因为一般在C语言中一般会先进行初始化,在C++中一般写在类里,这样我们在实例化的过程中就可以省去很多时间,而且避免了忘记初始化的风险。

构造函数特征:

1.函数名与类名相同

2.无返回值

3.对象实例化时编译器自动调用对应的构造函数

4.构造函数可以重载

所以构造函数实际上能够做到我们对象一定义出来就初始化了

class Date{
public:
    Date(){
        _year = 0;
        _month = 0;
        _day = 0;
    }
    //带参构造函数
    Date(int year, int month, int day){
        _year = year;
        _month = month;
        _day = day;
    }

	//全缺省,注意默认构造函数只能有一个,所以只能选一种我们推荐用全缺省方式的构造函数
	Date(int year=2022, int month = 2, int day = 20){
	    _year = year;
        _month = month;
        _day = day;
	}

    void date(int year, int month, int day){
        this->_year = year;
        this->_month = month;
        this->_day = day;
    }

    void Print(){
        cout << _year << "/" << _month << "/" << _day <<endl;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main(){
	Date day1; //注意这种是调用无参构造函数
	Date day2(2021,10,19); //带参构造函数

	Date day3(); //函数声明,返回一个日期类型的对象
}

Warning:

如果用户显示定义了构造函数,编译器将不再生成内置类型不会初始化 ,如int/char/double/指针等自定义类型会调用他的构造函数初始化,如struct/class/union

2. 析构函数

对象在销毁时会自动调用析构函数,完成类的一些资源清理工作

析构特征:

1.在类名的前面加上字符: ~

2.无参数无返回值

3.一个类有且只有一个析构函数。如果没有定义系统将自动生成默认的

4.对象生命周期结束时,C++编译系统自动调用析构函数

class SeqList
{
public :
	SeqList (int capacity = 10)
	 {
		_pData = (DataType*)malloc(capacity * sizeof(DataType));
		assert(_pData);
		_size = 0;
		_capacity = capacity;
	 }

	~SeqList()
	 {
		if (_pData)
		 {
			free(_pData ); // 释放堆上的空间
			_pData = NULL; // 将指针置为空
			_capacity = 0;
			_size = 0;
		 }
	 }
private :
	int* _pData ;
	size_t _size;
	size_t _capacity;

};

3. 拷贝函数

顾名思义就是拷贝一个一摸一样的对象

特征:

1.是构造函数的一个重载形式

2.参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用

下面就会引发无穷递归,解决办法就是在Date类型后面加一个引用,这里就变成了用别名区分

3. 如果未定义,系统生成默认的 拷贝构造函数。默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝成为浅拷贝

4. 赋值运算符重载

我们先了解一个概念叫运算符重载,具有其返回值类型,函数名以及参数列表

关键字:operator后面接需要重载的运算符符号

Warning:

1.作为类成员的重载函数时,其形参看起来比操作数数目少一个成员函数,实际上并不是这样子的,操作符有一个默认形参this,限定为第一个形参

2.以下符号不能重载:.* , :: . sizeof , ?: . .

3.我们定义operation一般在public里面而不是全局,因为如果我们修改不了private里面的成员变量,就保证不了封装性

特征:

1. 参数类型

2.返回值

3.检查是否自己给自己赋值

4. 返回*this

5. 一个类如果没有显示定义赋值运算符重载,编译器也会生成一个,完成对象按字节序的值拷贝

下面就简单实现了日期增加N天的运算符赋值

//Date day(2021,10,10);
//day += 20;
Date& Date::operator+=(int day){
    if(day<0){
        return *this -= -day;
    }else{
        _day += day;

        //如果日期不合法,进位
        while(_day > GetMonthDay(_year, _month)){

            _day -= GetMonthDay(_year, _month);
            ++_month;

            if(_month == 13){
                ++_year;
                _month = 1;
            }
        }
    }

    return *this;
}

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C++ 类和对象基础篇

    类是创建对象的模板,一个类可以创建多个对象,每个对象都是类类型的一个变量:创建对象的过程也叫类的实例化.每个对象都是类的一个具体实例(Instance),拥有类的成员变量和成员函数. 一.类的定义 一个简单的类的定义: class Student{ public: //成员变量 char *name; int age; float score; //成员函数 void say(){ cout<<name<<"的年龄是"<<age<<&qu

  • C++类和对象到底是什么

    目录 1.C++ 中的类 2.面向对象编程(Object Oriented Programming,OOP) 1.C++ 中的类 C++ 中的类(Class)可以看做C语言中结构体(Struct)的升级版.结构体是一种构造类型,可以包含若干成员变量,每个成员变量的类型可以不同:可以通过结构体来定义结构体变量,每个变量拥有相同的性质. 例如: #include <stdio.h> //定义结构体 Student struct Student{ //结构体包含的成员变量 char *name; i

  • C++类和对象基础详解

    目录 一.类和对象的基本概念 结构化程序设计 面向对象的程序设计 使用类的成员变量和成员函数 二.类和对象基础 类成员的可访问范围 构造函数(constructor) 基本概念 拷贝(复制)构造函数 类型转换构造函数 析构函数(destructors) 总结 一.类和对象的基本概念 结构化程序设计 C语言使用结构化程序设计: 程序 = 数据结构 + 算法 程序由全局变量以及众多相互调用的函数组成 .算法以函数的形式实现,用于对数据结构进行操作. 结构化程序设计的不足 1.结构化程序设计中,函数和

  • c++ 类和对象总结

    话不多说,我们直接进入主题: 对象:客观世界里的一切事物都可以看作是一个对象,每一个对象应当具有属性(静态特征,比如一个班级,一个专业,一个教室)和行为(动态特征,例如:学习,开会,体育比赛等)两个要素. 对象是由一组属性和一组行为构成的. 类(class):就是对象的类型,代表了某一批对象的共同特性和特征.类是对象的抽象,而对象是类的具体实例. 2.1 类的引入 在C语言中我们定义一个结构体是这样定义的: struct Student { int _age; char* _Gender; ch

  • C++之类和对象课后习题简单实例

    建立一个对象数组,内放5个学生的(学号,成绩),设立一个函数max,用指向对象的指针作函数参数,在max函数中找出5个学生的最高成绩者,并输出其学号. #include<iostream> using namespace std; class Student {public: Student(int=10,int=0); int number; int score; void display(); }; Student::Student(int num,int sco):number(num)

  • C++核心编程之类和对象详解

    目录 1.封装 1.1封装的意义 封装意义一: 封装意义二 1.2 struct 和 class 区别 1.3 成员属性设置为私有 总结 C++面向对象三大特性:封装.继承.多态 1.封装 1.1封装的意义 将属性和行为作为一个整体 将属性和行为加以权限控制 封装意义一: 语法:class 类名{ 访问权限: 属性 / 行为 }; //实例1 #define _CRT_SECURE_NO_WARNINGS 1 //求圆的周长 #include<iostream> using namespace

  • C++入门浅谈之类和对象

    目录 一.面向过程vs面向对象 二.类的限定符及封装 三.类的实例化 四.this指针 五.默认成员函数 1. 构造函数 2. 析构函数 3. 拷贝函数 4. 赋值运算符重载 总结 一.面向过程vs面向对象 C语言面向过程,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题 C++是基于面向对象,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成,C++不是纯面向对象的语言,C++既有面向过程,也有面向对象可以混合编程.C语言面向过程,数据和方法是分离的.CPP面向对象,数

  • 浅谈JavaScript 浏览器对象

    window window对象不但充当全局作用域,而且表示浏览器窗口. window对象有innerWidth和innerHeight属性,可以获取浏览器窗口的内部宽度和高度.内部宽高是指除去菜单栏.工具栏.边框等占位元素后,用于显示网页的净宽高.还有一个outerWidth和outerHeight属性,可以获取浏览器窗口的整个宽高. 补充: 网页可见区域宽:document.body.clientWidth 网页可见区域高:document.body.clientHeight 网页可见区域宽:

  • 浅谈js中对象的使用

    简单记录javascript中对象的使用 一.创建对象 //创建一个空对象 var o={}; //创建一个含有两个属性的对象,x.y var o2={x:12,y:'12',name:'JS'}; //此对象中的author属性的值还是一个对象 var o3={x:12,author:{name:'JS',age:23,address:'china'}}; //创建一个空对象和{}一样 var o4=new Object(); //给对象增加name属性 o4.name='JS' 上面使用了两

  • 浅谈Java回收对象的标记和对象的二次标记过程

    一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的清理. 至于怎么标记,一般有两种方法:引用计数和可达性分析. 引用计数实现起来比较简单,就是给对象添加一个引用计数器,每当有一个地方引用它时就加1,引用失效时就减1,当计数器为0的时候就标记为可回收.这种判断效率很高,但是很多主流的虚拟机并没有采用这种方法,主要是因为它很难解决几个对象之间循环引用的问题,虽然不怎么用了,但还是值得我们学习! public class Test

  • 浅谈hibernate中对象的3种状态_瞬时态、持久态、脱管态

    Hibernate的对象有3种状态,分别为:瞬时态(Transient). 持久态(Persistent).脱管态(Detached).处于持久态的对象也称为PO(Persistence Object),瞬时对象和脱管对象也称为VO(Value Object). • 瞬时态 由new命令开辟内存空间的java对象, eg. Person person = new Person("amigo", "女"); 如果没有变量对该对象进行引用,它将被java虚拟机回收. 瞬

  • 浅谈java 面对对象(抽象 继承 接口 多态)

    什么是继承? 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可. 多个类可以称为子类,单独这个类称为父类.超类或者基类. 子类可以直接访问父类中的非私有的属性和行为. 通过 extends 关键字让类与类之间产生继承关系. class SubDemo extends Demo{} //SubDemo是子类,Demo是父类 继承有什么好处? •提高代码的复用性. •让类与类之间产生了关系,是多态的前提. 继承的特点 1.Java只支

  • 浅谈Java实体对象的三种状态以及转换关系

    最新的Hibernate文档中为Hibernate对象定义了四种状态(原来是三种状态,面试的时候基本上问的也是三种状态),分别是:瞬时态(new, or transient).持久态(managed, or persistent).游状态(detached)和移除态(removed,以前Hibernate文档中定义的三种状态中没有移除态),如下图所示,就以前的Hibernate文档中移除态被视为是瞬时态. 瞬时态:当new一个实体对象后,这个对象处于瞬时态,即这个对象只是一个保存临时数据的内存区

  • 浅谈Django QuerySet对象(模型.objects)的常用方法

    准备工作: 新建一个项目,在项目中新家一个app,名字自取.将app添加值settings.py中,然后配置settings连接数据库. 在app中的models中新建模型: from django.db import models # Create your models here. class Author(models.Model): """作者模型""" name = models.CharField(max_length=100) ag

  • 浅谈java object对象在heap中的结构

    对象和其隐藏的秘密 java.lang.Object大家应该都很熟悉了,Object是java中一切对象的鼻祖. 接下来我们来对这个java对象的鼻祖进行一个详细的解剖分析,从而理解JVM的深层次的秘密. 工具当然是使用JOL: @Slf4j public class JolUsage { @Test public void useJol(){ log.info("{}", VM.current().details()); log.info("{}", ClassL

  • 浅谈JS包装对象

    目录 概述 定义 实例方法 原始类型与实例对象的自动转换 自定义方法 Boolean 对象 概述 Boolean 函数的类型转换作用 Number 对象 概述 静态属性 实例方法 自定义方法 String 对象 概述 静态方法 概述 定义 对象是JavaScript语言最主要的数据类型,三种原始类型的值--数值.字符串.布尔值--在一定条件下,也会自动转为对象,也就是原始类型的"包装对象"(wrapper). 所谓"包装对象",指的是与数值.字符串.布尔值分别相对应

随机推荐