首页 > 其他分享 >类和对象(1)

类和对象(1)

时间:2024-09-16 19:55:32浏览次数:10  
标签:函数 对象 成员 访问 int year public

个人主页:Jason_from_China-CSDN博客

所属栏目:C++系统性学习_Jason_from_China的博客-CSDN博客

所属栏目:C++知识点的补充_Jason_from_China的博客-CSDN博客

前言

类和对象是C++初阶比较难的篇章,这里的学习深度还是很深的,建议学习的小伙伴比这打一下代码。

类的定义格式

概念概述

  • class为定义类的关键字,Stack为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。
  • 为了区分成员变量,一般习惯上成员变量会加一个特殊标识,如成员变量前面或者后面加_ 或者 m 开头,注意C++中这个并不是强制的,只是一些惯例,具体看公司的要求。
  • C++中struct也可以定义类,C++兼容C中struct的用法,同时struct升级成了类,明显的变化是 struct中可以定义函数,一般情况下我们还是推荐用class定义类。
  • 定义在类内的成员函数默认为inline。

代码实现

//类的定义格式

//class是定义类的关键字
class MyClass
{
public://公有
	MyClass();
	~MyClass();

private://私有

};

MyClass::MyClass()//构造函数
{
}

MyClass::~MyClass()//析构函数
{
}



//结构体struct为类的名字
//同理
struct MyStruct
{
public:
private:
};

 访问限定符

概念概述

  • C++一种实现封装的方式,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
  • public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访问,protected和private是一样的,以后继承章节才能体现出他们的区别。 
  • 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果没有后面没有访问限定符,作用域就到 }即类结束。 
  • class定义成员没有被访问限定符修饰时默认为private,struct默认为public。 
  • 一般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。

访问限定符的符号

在C++中,访问限定符用于控制类成员的访问权限。主要有三种访问限定符:

  1. public:公开的,可以被任何外部代码访问。
  2. protected:受保护的,可以被类本身以及其派生类访问。
  3. private:私有的,只能被类本身访问。

访问限定符的使用public(公有的):

默认情况下,如果不指定访问限定符,成员就是公开的。公开成员可以在类的任何对象上被访问,也可以在派生类中被访问(除非被隐藏)。

class MyClass {
public:
    int publicVar; // 公开成员,可以被任何外部代码访问
    void publicFunc() { /* ... */ } // 公开成员函数
};

这里我们可以看见,类外面是可以访问私有变量的

访问限定符的使用private(私有变量):

私有成员只能被类本身访问。它们不能被外部代码访问,也不能被派生类访问。

class MyClass {
private:
    int privateVar; // 私有成员,只能被类本身访问
    void privateFunc() { /* ... */ }
public:
    void publicFunc() {
        privateVar = 20; // 正确,类本身可以访问私有成员
        privateFunc(); // 正确
    }
};

在这里我们可以看到,如果放到私有变量里面,我们可以看到类比外面是无法访问类里面的私有变量的。

访问限定符的使用protected:

  1. 类内部访问:类本身可以访问其 protected 成员。
  2. 派生类访问:从该类派生出的子类也可以访问基类的 protected 成员。
  3. 外部访问限制:类外部的代码(即不是类本身也不是派生类)不能直接访问 protected 成员。
//基类
class BaseClass 
{
protected:
    int protectedVar; // 受保护成员,只能被类本身和派生类访问
    void protectedFunc() { /* ... */ }
};

// 这里是派生类,protected修饰的可以在派生类里面访问
class DerivedClass : public BaseClass 
{
public:
    void accessProtectedMembers() {
        protectedVar = 10; // 正确,派生类可以访问基类的受保护成员
        protectedFunc(); // 正确
    }
};

通过使用派生类,你可以创建更加灵活和可重用的代码,同时保持代码的组织性和清晰性。

需要注意的小点:

struct

struct MyStruct
{
	//公有成员变量
	void Func()
	{
		cout << "struct 公有成员变量 " << endl;
	}
public://公有成员变量


private://私有变量

};

class

class Date
{
	//私有成员函数变量
	void Func();
public://公有
	//构造函数(全缺省构造函数)
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	//私有成员函数变量
	int _year;
	int _month;
	int _day;
};

类域

概念概述

  • 类定义了一个新的作用域,类的所有成员都在类的作用域中,在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。
  • 类域影响的是编译的查找规则,下面程序中Init如果不指定类域Stack,那么编译器就把Init当成全局函数,那么编译时,找不到array等成员的声明/定义在哪里,就会报错。指定类域Stack,就是知道Init是成员函数,当前域找不到的array等成员,就会到类域中去查找。

 放到类里面实现(内联函数)

放到类里面实现此时是不需要写inline,编译器会自动认为是内联函数,从而进行编译

在类里面的实现和使用

在类域里面的使用,我们可以称之为内联函数

这也是类的最大特点,可以直接定义函数

class Date
{
public://公有
	//构造函数(全缺省构造函数)//内联函数
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	void Func2();
private:
	//私有成员函数变量
	int _year;
	int _month;
	int _day;
};

类域的使用( ::)

在类外面的实现和使用

这里就涉及到,头文件和实现文件了,一般是把类放到.h文件里面,把实现放到.cpp文件里面

//.h
#include<iostream>
using namespace std;//取消打印折叠空间

class Date
{
public://公有
	void Func2();

private://私有

};

//类域的调用
void Date::Func2()
{
	cout << "类域的调用:" << endl;
}


此时我们发现我们去实现Func2,需要到类域里面去访问。

当然,我们也可以把类放到头文件,把实现放到实现文件里面,这个都是很灵活的

类的对象大小(内存对齐)

这里声明一下,类的对象大小其实和C语言里面结构体内存对齐的篇章差不大多,所以可以先看一下这一篇章,其实对于对象大小的内存对齐,主要就是会对齐,知道为什么需要有内存对齐就可以了

C语言-结构体的内存对齐(重点)_结构体内存对齐-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/Jason_from_China/article/details/137005772

this指针

概念概述

  • Date 类中有 Init 与 Print 两个成员函数,函数体中没有关于不同对象的区分,那当 d1 调用 Init 和 Print 函数时,该函数是如何知道应该访问的是 d1 对象还是 d2 对象呢?那么这里就要看到 C++ 给了一个隐含的 this 指针解决这里的问题。
  • 编译器编译后,类的成员函数默认都会在形参第一个位置,增加一个当前类类型的指针,叫做 this 指针。比如 Date 类的 Init 的真实原型为,void Init (Date* const this, int year, int month, int day)。
  • 类的成员函数中访问成员变量,本质都是通过 this 指针访问的,如 Init 函数中给_year 赋值,this-> _year = year。
  • C++ 规定不能在实参和形参的位置显式的写 this 指针 (编译时编译器会处理),但是可以在函数体内显式使用 this 指针。

this指针的具体使用

举例1:
//.h文件
class Date
{
public://公有
	//构造函数(全缺省构造函数)
	
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print2();
	void Print1()
	{
		cout <<"类里面实现函数调用:" << _year << "/" << _month << "/" << _day << endl;
	}

private:
	//私有成员函数变量
	int _year;
	int _month;
	int _day;
};
//类外面实现函数调用
//void Date::Print2(Date* const this)
void Date::Print2()
{
	cout << "类外面实现函数调用:" << _year << "/" << _month << "/" << _day << endl;

	//完全书写
	std::cout << "类外面实现函数调用:" << this->_year << "/" << this->_month << "/" << this->_day << std::endl;
	
}

//.cpp的实现
#include"test.h"
int main()
{
	cout << "类的定义格式:" << endl;

	//初始化需要默认构造函数,默认构造函数是编译器自带的初始化,以及全缺省构造函数,以及无参数构造函数
	//对象1
	Date d1;
	d1.Print1();//这里等同于 d1.Print1(&d1);但是这里是&是不传递参数的,也是不会写的,只是类似于传递参数由this接收参数

	//对象2
	Date d2(2, 2, 2);
	d2.Print2();//这里等同于 d1.Print1(&d1);但是这里是&是不传递参数的,也是不会写的,只是类似于传递参数由this接收参数
	return 0;
}

简单的说就是调用函数的时候,是有一个this指针指向对象的,因为C++支持函数重载,编译器会自己找到匹配的对象,这里如何找到,就是依靠this指针

举例2:

注意事项

注意事项1:

函数传参的时候,不支持显示写

注意事项2:

使用的时候支持显示写,但是不写也会直接默认存在

注意事项3:

静态成员函数是没有this指针的

在C++中,静态成员函数是与类相关联的,而不是与类的任何特定对象相关联。因此,静态成员函数不依赖于任何对象实例,它们可以在没有创建类的对象的情况下被调用。由于静态成员函数不与任何特定的对象实例相关联,它们无法访问类的非静态成员变量或成员函数,因为这些成员需要通过 this 指针来访问。

静态成员函数是用static修饰的成员函数。

 

静态成员函数(静态成员函数是用static修饰的成员函数。):

 
  1. 静态成员函数不属于特定的对象,它是类的一部分而不是对象的一部分。
  2. 可以通过类名直接调用,无需通过对象来调用,例如ClassName::staticFunctionName()
  3. 静态成员函数不能访问非静态成员变量,因为它没有this指针来指向特定的对象。但可以访问静态成员变量。

C++内存区域划分

声明:

这里是知识是很重要的,以我的水平是没有办法很好的讲解出来,所以作为了解放到最下面,这个知识主要是函数栈帧的知识,感兴趣的伙伴可以去查找一下,或者单纯的了解一下也是没有什么问题的

在 C++ 中,内存主要分为以下几个区域:

 
  1. 栈(Stack)

    • 存储局部变量、函数参数等。
    • 由编译器自动管理内存的分配和释放。当函数被调用时,为函数的局部变量和参数在栈上分配空间;当函数返回时,这些空间被自动释放。
    • 空间相对较小,增长方向是从高地址向低地址。
  2. 堆(Heap)

    • 用于动态分配内存,通过 newmalloc等操作符进行分配,通过 deletefree等进行释放。
    • 程序员需要手动管理堆内存的分配和释放,若管理不当可能会导致内存泄漏或悬空指针等问题。
    • 空间相对较大,可根据需要动态增长。
  3. 全局 / 静态存储区

    • 存储全局变量和静态变量。
    • 全局变量在程序启动时分配内存,在程序结束时释放;静态变量根据其作用域在不同的时间点分配和释放内存。
  4. 常量存储区

    • 存储常量,如字符串常量、常量数值等。
    • 这些常量在程序运行期间不能被修改。
  5. 代码区

    • 存储程序的二进制代码。
    • 这个区域通常是只读的,防止程序的代码被意外修改。
  6. 这里我找了这两张图,方便了解

标签:函数,对象,成员,访问,int,year,public
From: https://blog.csdn.net/Jason_from_China/article/details/142209234

相关文章

  • Day20笔记-面向对象&类和对象&类中的属性和函数&构造和析构函数
    一、面向对象基础1.概念1.1面向对象的设计思想面向对象是基于万物皆对象这个哲学观点,在Python中,一切皆对象举例说明:​案例一:我想要吃大盘鸡​面向过程面向对象​1.自己去买菜1.委托一个会砍价的人帮忙去买菜​2.自己择菜2.委托一个临时工帮忙择菜​3.自己......
  • Day11.面向对象编程OOP(3)
    多态动态编译:类型:可扩展性即同一种方法可以根据发送对象的不同而采用多种不同的行为方式一个对象的实际类型是确定的,但可以指向对象的引用的类型有很多多态注意事项:多态是方法的多态,属性没有多态父类和子类有联系类型转换异常:ClassCastException存在条件:继承......
  • urllib自定义opener对象设置代理IP
    urllib.request.urlopen()源代码——urlopen()在干什么返回opener.open(url,data,timeout)方法的结果 _opener=None#_opener被赋值为Nonedefurlopen(url,data=None,timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*,cafile=None,capath=None,cadefault=......
  • Day10.面向对象编程OOP(2)
    封装该露的露,该藏的藏高内聚,低耦合:高内聚:类的内部数据操作细节自己完成,不允许外部干涉低耦合:仅暴露少量的方法给外部使用提高程序的安全性,保护数据隐藏代码的实现细节统一接口提高系统的可维护性packagecom.dongfang.oop.Demo04;//类publicclassDemo01......
  • C++中对象的延迟构造
    本文并不讨论“延迟初始化”或者是“懒加载的单例”那样的东西,本文要讨论的是分配某一类型所需的空间后不对类型进行构造(即对象的lifetime没有开始),更通俗点说,就是跳过对象的构造函数执行。使用场景我们知道,不管是定义某个类型的对象还是用operatornew申请内存,对象的构造函数都......
  • 对象的创建方式:浅拷贝和深拷贝
    对象的创建方式:浅拷贝和深拷贝前言一、值传递和引用传递二、浅拷贝和深拷贝的理解1浅拷贝2.深拷贝三、代码验证和实现3.1浅拷贝的代码实现结果分析3.2深拷贝的代码实现一、实现cloneable接口结果分析实现Cloneable接口并重写方法的缺点二、实现序列化前言今......
  • chapter08 面向对象编程高级 知识点总结Note
    文章目录static修饰符单例设计模式main()方法类的成员代码块实例变量赋值位置顺序final关键字abstract关键字使用抽象应用模板方法设计接口语法应用(多态匿名实现类)jdk8jdk9接口新特性类的成员内部类枚举类(自定义enum方法实现接口)注解常用注解与JUnit单元测试......
  • 快速掌握类和对象
    目录1.面向对象的概念1.1面向对象的编程步骤2.类2.1类的详解2.2类的实例化---对象3.对象3.1对象的构造及初始化3.2构造方法3.3默认初始化4.this关键字5.static关键字5.1为什么要有static5.2static修饰成员变量---类变量5.3static修饰成员方法---类......
  • Spring 源码解读:使用FactoryBean创建复杂对象的实现
    引言在Spring框架中,FactoryBean是一个特殊的Bean,它允许开发者通过实现FactoryBean接口来控制Bean的创建过程,特别适用于创建复杂对象。FactoryBean可以将复杂对象的创建逻辑与业务逻辑分离,提供更高的灵活性和可扩展性。在本篇文章中,我们将手动实现一个FactoryBean接口,展示......
  • windows C++ 并行编程-并行容器和对象
    并行模式库(PPL)包括几个容器和对象,这些容器和对象提供对其元素的线程安全访问。并发容器提供对最重要操作的并发安全访问。在这里,并发安全意味着指针或迭代器始终有效。它不保证元素初始化或特定的遍历顺序。这些容器的功能与C++标准库提供的功能类似。例如,concurren......