C++的类和对象入门
目录
目录
目录
一、类
1.1类的定义
1.2访问限定符
1.3类域
1.4类的命名规范
1.5class和struct的默认访问权限
二、类的实例化
2.2对象的大小和存储
2.3空类的大小
三、this指针
3.1this指针的定义
3.2this指针的作用
3.2.1区分同名变量和局部变量
3.2.2返回对象自身的引用
结语
一起学习的小伙伴们,今天我们这篇文章将进入到C++里迷人的类和对象部分的入门,那么话不多说,和我一起进入学习吧!
一、类
1.1类的定义
在C++中,类的定义基本形式如下:
class 类名 {
// 访问修饰符(public、private、protected)
// 成员变量(数据成员)声明
// 成员函数(方法)声明
};
例如:
class Rectangle {
public:
int width;
int height;
int getArea(); // 成员函数声明
};
// 成员函数定义在类外,需使用作用域解析运算符 ::
int Rectangle::getArea() {
return width * height;
}
类把数据(成员变量)和操作这些数据的函数(成员函数)组合在一起,public成员可在类外访问,private成员默认只能在类内访问,protected用于继承相关的访问控制等情况。与C需要typedefin不同的是,类的类名就是类型,在使用的时候可以直接通过类名来初始化。
1.2访问限定符
- C++一种实现封装的方式,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
- public修饰的成员在类外可以直接被访问;protected和private修饰的成员在类外不能直接被访间,protected和private是一样的,以后继承章节才能体现出他们的区别。
- 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止,如果后面没有访问限定符,作用域就到}即类结束。
- class定义成员没有被访问限定符修饰时默认为private,struct默认为public.
- 一般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。
1.3类域
类的作用域,决定了在类内定义的成员的可访问性。在类外使用类内成员定义函数的时候。要使用作用域解析符::指明这个成员是属于哪个类。
include <iostream>
using namespace std;
class Stack
{
public:
void Init(int n = 4);//缺省参数4
private:
//自定义域内变量
};
void Stack::Init(int n)//使用::来访问域内成员函数
{//函数体
}
并且,::确定了函数属于什么类,那么相应的,编译器可以在作用域里查找自定义成员变量。
1.4类的命名规范
有三种命名方式,主要作用是用于区分函数参数和类的成员变量,提高代码的可学性和维护性。
1、在成员变量前使用下划线 _
2、在成员变量前使用m_前缀
3、使用驼峰命名法
class Date {
private:
int _year; // 使用下划线前缀
int m_month; // 使用 m_ 前缀
int dayOfMonth; // 使用驼峰命名法
public:
void SetDate(int year, int month, int day) {
_year = year;
m_month = month;
dayOfMonth = day;
}
};
1.5class和struct的默认访问权限
class:class的默认访问权限是private,不能直接在外部引用。
struct:struct的默认访问权限是public,可以在外部直接引用。
二、类的实例化
关于类的实例化,首先先说类的定义,类是对对象的的抽象描述,它提供了对象的结构和行为,但是类的本身并不占用物理空间,只有在实例化操作的时候才会分配空间。
那么可以形象的理解成,类如何建造房屋的图纸,图纸不会占用土地,只有依照这个图纸建造的房屋才会占用土地。
#include <iostream>
using namespace std;
class Date {
public:
void Init(int year, int month, int day) {
_year = year;
_month = month;
_day = day;
}
void Print() {
cout << _year << "/" << _month << "/" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main() {
Date d1;
d1.Init(2024, 3, 31);
d1.Print();
Date d2;
d2.Init(2024, 7, 5);
d2.Print();
return 0;
}
说明:这里的class Date是一个类
Date d1,Date d2是对类的两个实例化,在这里开辟了内存空间。
2.2对象的大小和存储
首先我们知道,类和结构体和一大区别是,在类中不仅可以存在成员变量,还可以不通过指针变量引用外界函数来直接在类里面定义函数。
注意:成员变量需要分配空间,但成员函数是存储在单独代码段中的一段指令。
#include <iostream> using namespace std; class A { private: char _ch; // 1 字节 int _i; // 4 字节 }; int main() { A a; cout << sizeof(a) << endl; // 输出对象的大小 return 0; }
注意:这里运行结果是8并不是5,下面是具体解释:
在计算对象的大小的时候,会存在内存对其的情况,内存对其可以方便读取提高效率。
内存对齐指的是计算机系统为了提高数据访问效率,将数据存放在内存中按照特定规则对齐的方式。
基本数据类型会按照其自身大小或者特定对齐模数,被放置在内存地址为其大小倍数的位置上。比如4字节的整型,通常会放在能被4整除的内存地址处。结构体中各成员也遵循对齐规则,整体大小通常是其内部最大成员大小的整数倍。这样做能加快CPU读取数据速度,减少内存访问次数,但会造成一定的内存空间浪费。
2.3空类的大小
已知,类的大小是有类的成员变量决定,成员函数并不影响类的大小。那么如果一个类中没有成员函数,那么它的大小是多少呢?
直接给结论:空类的空间大小是一个字节。
为什么?下面是解释:
1、区分不同对象的地址:如果是零个字节,那么就会导致多个对象共享一个内存地址,导致冲突。
2、确保类的指针行为一致:指向不同对象时,他们也必须指向不同的内存地址,所以必须要有一字节的大小证明这个类“来过”
#include<iostream>
using namespace std;
class EmptyClass {
public:
void Print() {
cout << "This is an empty class!" << endl;
}
};
int main() {
EmptyClass e1, e2;
cout << "EmptyClass 对象 e1 的大小: " << sizeof(e1) << " 字节" << endl;
cout << "EmptyClass 对象 e2 的大小: " << sizeof(e2) << " 字节" << endl;
return 0;
}
三、this指针
3.1this指针的定义
this指针是隐含于每一个非静态成员函数中的特殊指针,它指向这个成员函数的对象。
例如Date类Init函数实际上是这样的
#include <iostream>
using namespace std;
class Date {
public:
void Init(Date*const this,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;
};
请注意,在C++中,不能在实参1和形参的位置上显写this指针,这样会报错,编译器会自己处理对象之间的矛盾,但是可以在函数体里面使用this指针。
3.2this指针的作用
当我们在一个对象上去调用成员函数的时候,编译器一般会把该对象的地址作为this指针传递给成员函数。
所以,总的来说:
类的成员函数中去访问成员变量其实都是通过this指针去访问的,例如上文中在成员函数中的赋值操作。
3.2.1区分同名变量和局部变量
#include <iostream> using namespace std; class Date { public: void Init(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; };
3.2.2返回对象自身的引用
Zyzzyz& add(int num) { this->a +=num; return *this; }
这样就可以通过使用 :类.add(n).add(m)这种格式来连续链式调用函数。
3.3.3获取对象的地址
#include <iostream> class Zyzzzyz { public: void printAddress() { std::cout<<"该对象的地址是:"<<this<<std::endl; } } int main() { Zyzzzyz obj; obj.printAddress(); return 0; }
这样就可以通过this指针来得到obj的地址,并打印出来显示。
结语
至此,本文介绍的关于C++入门的部分知识正式结束,日后我会更新更多关于C++的基础入门知识,如果本文能帮助到阅读文章的你,就请点赞转发收藏吧,您的支持也是我继续学习和更新的动力,感谢支持!!