朋友们好,这篇播客我们继续C++的初阶学习,现在对一些C++的入门知识做了些总结,整理出来一篇博客供我们一起复习和学习,如果文章中有理解不当的地方,还希望朋友们在评论区指出,我们相互学习,共同进步!
C++面向对象的三大特性为:封装、继承、多态
C++认为万事万物都皆为对象,对象上有其属性和行为
例如:
人可以作为对象,属性有姓名、年龄、身高、体重…,行为有走、跑、跳、吃饭、唱歌…
车也可以作为对象,属性有轮胎、方向盘、车灯…,行为有载人、放音乐、放空调…
具有相同性质的对象,我们可以抽象称为类,人属于人类,车属于车类
面向对象编程思想还需要我们在学习过程中不断的理解!
封装是C++面向对象的三大特征之一,将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
封装的意义:
在设计类的时候,属性和行为写在一起,表现事物,语法: class 类名{ 访问权限: 属性 / 行为 };
例如设计一个圆类:
class Circle
{
public: //访问权限 公共的权限
//属性
int m_r;//半径
//行为
//获取到圆的周长
double calculateZC()
{
//2 * pi * r
//获取圆的周长
return 2 * PI * m_r;
}
};
类的两种定义方式:
注:声明和定义的区别是有无开辟空间。
类在设计时,可以把属性和行为放在不同的权限下,加以控制。
三种权限的区别:
公共权限 public 类内可以访问 类外可以访问
保护权限 protected 类内可以访问 类外不可以访问
私有权限 private 类内可以访问 类外不可以访问
示例:
class Person
{
//姓名 公共权限
public:
string m_Name;
//汽车 保护权限
protected:
string m_Car;
//银行卡密码 私有权限
private:
int m_Password;
public:
void func()
{
m_Name = "张三";
m_Car = "拖拉机";
m_Password = 123456;
}
};
int main() {
Person p;
p.m_Name = "李四";
//p.m_Car = "奔驰"; //保护权限类外访问不到
//p.m_Password = 123; //私有权限类外访问不到
system("pause");
return 0;
}
m_Car、m_Password分别为保护权限和私有权限,在类外不可直接访问。
访问权限符说明:
注意:访问限定符只在编译的时候有用,当数据映射到内存后,没有任何访问限定符的区别。
在C++中 struct和class唯一区别就在于 默认的访问权限不同
区别:
示例:
class C1
{
int m_A; //默认是私有权限
};
struct C2
{
int m_A; //默认是公共权限
};
int main() {
C1 c1;
c1.m_A = 10; //错误,访问权限是私有
C2 c2;
c2.m_A = 10; //正确,访问权限是公共
system("pause");
return 0;
}
都在默认权限时,c1.m_A访问不到,c2.m_A可以访问。
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类外定义成员,需要使用::作用域解析符指明成员属于哪个类域。
示例:
class Circle
{
public: //访问权限 公共的权限
//属性
int m_r;//半径
//行为
//获取到圆的周长
double calculateZC();
};
double Circle::calculateZC()
{
//2 * pi * r
//获取圆的周长
return 2 * PI * m_r;
}
类作为一种自定义类型,同样可以定义变量,用类类型创建对象的过程,称为类的实例化。
一个类可以实例化出多个对象,实例化出的对象,占用实际的物理空间,存储类非静态成员变量。
类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?
在C++中,类内的成员变量和成员函数分开存储!!!
因为如果类实例化多个对象,那么在每个对象中都会保存一份代码,相同的代码保存多次,浪费空间,所以就分开存储。
只有非静态成员变量才属于类的对象上!,其他的成员函数,静态成员变量,静态成员函数都不在类对象上。
结论:一个类的大小,实际就是该类中“成员变量”之和,也要遵循内存对齐,注意空类的大小,编译器给了空类一个字节来唯一标识这个类。
总结:没有成员变量的类对象,编译会给他们分配1byte占位,表示对象存在过
class Person {
public:
Person() {
mA = 0;
}
//非静态成员变量占对象空间
int mA;
//静态成员变量不占对象空间
static int mB;
//函数也不占对象空间,所有函数共享一个函数实例
void func() {
cout << "mA:" << this->mA << endl;
}
//静态成员函数也不占对象空间
static void sfunc() {
}
};
int main() {
cout << sizeof(Person) << endl;
system("pause");
return 0;
}
我们知道在C++中成员变量和成员函数是分开存储的,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码
那么问题是:这一块代码是如何区分哪个对象调用自己的呢?
c++通过提供特殊的对象指针,this指针,解决上述问题。即:C++编译器给每个非静态的成员函数增加一个隐藏的指针参数,让该指针指向当前对象,在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作都是对用户透明的,即用户不需要来传递,编译器自动完成。
class Person
{
public:
Person(int age)
{
//1、当形参和成员变量同名时,可用this指针来区分
this->age = age;
}
Person& PersonAddPerson(Person p)
{
this->age += p.age;
//返回对象本身
return *this;
}
int age;
};
void test01()
{
Person p1(10);
cout << "p1.age = " << p1.age << endl;
Person p2(10);
p2.PersonAddPerson(p1).PersonAddPerson(p1).PersonAddPerson(p1);
cout << "p2.age = " << p2.age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
C++中空指针也是可以调用成员函数的,但是也要注意该成员函数有没有用到非静态成员变量,如果用到需要对this指针加以判断保证代码的健壮性
为什么空指针可以访问成员函数呢?
理解:因为成员函数并没有存在类对象的空间上,而是在公共代码区,编译链接的时候只会利用函数名去找地址,所以不存在对空指针的解引用。
//空指针访问成员函数
class Person {
public:
void ShowClassName() {
cout << "我是Person类!" << endl;
}
void ShowPerson() {
if (this == NULL) {
return;
}
cout << mAge << endl;
}
public:
int mAge;
};
void test01()
{
Person * p = NULL;
p->ShowClassName(); //空指针,可以调用成员函数
p->ShowPerson(); //但是如果成员函数中用到了this指针,就不可以了
}
int main() {
test01();
system("pause");
return 0;
}
上述代码中,如果成员函数中用到了this指针,需要对this指针加以判断以增强代码的健壮性!