一、类的引入
在C语言的学习中,有一种自定义类型的数据集合——结构体,但是在结构体中只存在一系列具有相同类型或不同类型的数据,并不能在里面自定义函数。如下:
struct Student
{
char _name[10];
int _age;
int _height;
};
C++身为C语言的继承,它不仅可以定义结构体,而且可以在结构体中定义函数,而这种结构体的定义,在C++中更喜欢用 class 来代替。如下:
class Student //struct Student
{
char _name[10];
int _age;
int _height;
void InforInit(const char* name, const int age, const int height)
{
strcpy(_name,name);
_age = age;
_height = height;
}
};
二、类的定义
类定义的格式如下:
class + 类的名字
{
自定义的成员类型和成员变量。
};//不要忘记了分号喔。
类有两种定义方式:
第一种是将定义直接写在类体内。(需要注意的是:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。)
第二种是在类内声明,类外定义。
类的声明放到Person.h的头文件中
#include<iostream>
using namespace std;
class Person
{
char _name[10];
int _age;
int _phonenum;
void InforPrint();
};
成员函数的定义放到Person.cpp的文件中
#include"Person.h"
void Person::InforPrint()
{
cout<<_name<<_age<<_phonenum<<endl;
}
本人建议用第二种,避免造成不必要的麻烦。
三、类的访问限定符及封装
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其 接口提供给外部的用户使用。
所以为了实现这种封装,有了访问限定符:
- public
- private
- protected
class Student
{
private: //也可以不加,类中默认为私有访问
char _name[20];
char _gender[3];
int _age;
public:
void SetStudentInfo(const char* name, const char* gender, int age)
{
strcpy(_name, name);
strcpy(_gender, gender);
_age = age;
}
void PrintStudentInfo()
{
cout<<_name<<" "<<_gender<<" "<<_age<<endl;
}
};
在类的内部(定义类的代码内部),无论成员被声明为public、 protected 还是 private,都可以互相访问的,没有访问权限的限制。
在类的外部(定义类的代码之外),只能通过对象访问成员,并 且只能访问 public 属性的成员,不能访问 private、protected 属性的成员。
【注意】:在C++中class的默认访问权限为private,struct为public(因为struct要兼容C)
关于封装
面向对象的三大特性:封装、继承、多态。
什么是封装呢?
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。封装的意义在于保护或者防止代码(数据)被我们无意中破坏。
封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全。数据封装引申出了另一个重要的 OOP 概念,即数据隐藏。
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
class Add{
public:
// 对外的接口
void AddInit(int i = 0)
{
total = i;
}
// 对外的接口
void addNum(int number)
{
total += number;
}
// 对外的接口
int getTotal()
{
return total;
};
private:
// 对外隐藏的数据
int total;
};
四、类的作用域
一个类定义了一个新的作用域,类的所有成员都在类的作用域中。当类的成员函数的定义在类外时,需要使用作用域解析符 ::来指名该函数属于哪一个类域。
class Person
{
char _name[10];
int _age;
int _phonenum;
void InforPrint();
};
void Person::InforPrint()//声明该函数属于person这个类域
{
cout<<_name<<_age<<_phonenum<<endl;
}
五、类的大小
一个类的大小,和结构体大小的计算方法一样,根据”成员变量之和“,再进行内存对齐。
【注意】:一个空类的大小是多少呢?
由于空类比较特殊,所以编译器给了空类一个字节来唯一标识这个类。
六、隐身的this指针
- this指针是一个隐含于每一个成员函数中的特殊指针。
- 它是一个指向正操作该成员函数的对象。当对一个对象调用成员
函数时,编译程序先将对象的地址赋给this指针,然后调用成员
函数。每次成员函数存取数据成员时,C++编译器将根据this指
针所指向的对象来确定应该引用哪一个对象的数据成员。 - 通常this指针在系统中是隐含存在的,也可以把它显式表示出来。
#include<iostream>
using namespace std;
class A
{
int i;
public:
void set(int x)
{
this->i = x;
cout<<"this指针保存的内存地址为:"<<this<<endl;
}
};
int main()
{
A a;
a.set(9);
cout<<"对象a所在的内存地址为:"<<&a<<endl;
return 0;
}
运行结果:
this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针。 this指针实际储存在栈中。