类是 C++ 的核心特性,是一种用户自定义的数据类型,它是一种封装了数据和函数的组合。类中的数据称为成员变量,函数称为成员函数。类可以被看作是一种模板,可以用来创建具有相同属性和行为的多个对象。
用生活例子来解释:对象相当于人类,属性是指人的姓名,年龄,身高,体重........行为代表人所作的一系列动作走,跑,跳,骑车.........
c++面向对象三大特征:封装,继承,多态
一.c++类&对象
1.c++类的定义
定义一个类需要使用关键字 class,然后指定类的名称,类的主体是包含在一对花括号中,主体包含类的成员变量和成员函数。定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么(属性),以及可以在这个对象上执行哪些操作(行为)。
以下示例使用关键字class定义数据类型people,包含三个成员变量和一个成员函数。
2. 定义c++对象
声明类的对象,就像声明基本类型的变量一样。下面的语句声明了类 person 的两个对象p1,p2:
3.访问数据成员
类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问。
#include <iostream>
using namespace std;
#include <string>
class person{
public: //公共权限
//成员函数(属性)
string name; //姓名
int height; //身高
int weight; //体重
//成员函数(行为) 显示姓名,身高和体重
void showperson(){
cout<<"姓名"<<name<<"身高"<<height<<"体重"<<weight<<endl;
}
};
int main(){
//创建具体的人,实例化对象
person p1;
person p2;
//给对象p1的属性进行赋值操作
p1.name="张三";
p1.height=163;
p1.weight=105;
//显示人的信息
p1.showperson();
//给对象p2的属性进行赋值操作
p2.name="李四";
p2.height=180;
p2.weight=148;
//显示人的信息
p2.showperson();
return 0;
}
需要注意的是,私有的成员和受保护的成员不能使用直接成员访问运算符 (.) 来直接访问。
二.c++数据的封装
1.概念
数据封装是一种把数据和操作数据的函数捆绑在一起的机制,通过将数据和操作数据的函数封装在一个类中来实现。通俗来讲是将属性和行为作为一个整体,表现生活中的事物。同时,将属性和行为加以权限设置。这种封装确保了数据的私有性和完整性,防止了外部代码对其直接访问和修改。
数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制。
类包含私有成员 private、保护成员 protected 和公有成员 public 成员。默认情况下,在类中定义的所有项目都是私有的。(class与struct唯一区别:默认权限不同。class默认权限为私有,struct默认权限为公共)
- private: 私有成员只能在类的内部访问,不能被类的外部代码直接访问。
- public: 公有成员可以被类的外部代码直接访问。
- protected: 受保护成员可以被类和其派生类访问。
2.示例
#include <iostream>
using namespace std;
#include <string>
class person {
private:
string name;
int age;
public:
// 构造函数(赋值)
person(string personName, int personAge) {
name = personName;
age = personAge;
}
// 访问
string getName() {
return name;
}
int getAge() {
return age;
}
// 修改
void setName(string personName) {
name = personName;
}
void setAge(int personAge) {
if (personAge > 0) {
age = personAge;
} else {
cout << "Invalid age!" << endl;
}
}
// 打印个人信息
void printInfo() {
cout << "Name: " << name << ", Age: " << age << endl;
}
};
int main() {
// 创建一个 person 对象
person p1("Alice", 20);
// 访问和修改数据
p1.printInfo();
p1.setName("Bob");
p1.setAge(22);
p1.printInfo();
return 0;
}
变量 name和 age都是私有的(private)。它们只能被 person类中的其他成员访问,而不能被程序中其他部分访问。这是实现封装的一种方式。为了使类中的成员变成公有的(即程序中的其他部分也能访问),必须在这些成员前使用 public 关键字进行声明。
三.c++继承
1.概念
继承:创建一个类时,不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类(父类),新建的类称为派生类(子类)。例如,哺乳动物是动物,狗是哺乳动物,因此,狗是动物。
语法:
其中,继承方式是 public、protected 或 private 其中的一个,默认情况下为 private
示例如下
#include <iostream>
using namespace std;
// 基类
class message
{
public:
void city()
{
cout<<"北京"<<endl;
}
void school()
{
cout<<"实验中学"<<endl;
}
};
// 派生类
class student1: public message
{
public:
void grade()
{
cout<<710<<endl;
}
};
class student2: public message
{
public:
void grade()
{
cout<<657<<endl;
}
};
int main(void)
{
student1 s1;
s1.city();
s1.school();
s1.grade();
student s2;
s2.city();
s2.school();
s3.grade();
return 0;
}
2.访问权限和继承
派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。
个派生类继承了所有的基类方法,但下列情况除外:
- 基类的构造函数、析构函数和拷贝构造函数。
- 基类的重载运算符。
- 基类的友元函数。
3.继承类型
当一个类派生自基类,该基类可以被继承为 public、protected 或 private 几种类型。继承类型是通过上面讲解的继承方式 来指定的。我们几乎不使用 protected 或 private 继承,通常用 public 继承。当使用不同类型的继承时,遵循以下几个规则:
- 公有继承(public):当一个类派生自公有基类时,基类的公有成员也是派生类的公有成员,基类的保护成员也是派生类的保护成员,基类的私有成员不能直接被派生类访问,但是可以通过调用基类的公有和保护成员来访问。
- 保护继承(protected): 当一个类派生自保护基类时,基类的公有和保护成员将成为派生类的保护成员。
- 私有继承(private):当一个类派生自私有基类时,基类的公有和保护成员将成为派生类的私有成员。
4.多继承
多继承即一个子类可以有多个父类,它继承了多个父类的特性。
C++ 类可以从多个类继承成员,语法如下:
四.c++多态
多态按字面的意思就是多种形态。当类之间存在层次结构,并且类之间是通过继承关联时,就会用到多态。多态使得代码更加灵活和通用,程序可以通过基类指针或引用来操作不同类型的对象,而不需要显式区分对象类型。这样可以使代码更具扩展性,在增加新的形状类时不需要修改主程序。
注意,只有通过基类的指针或引用调用虚函数时,才会发生多态。
虚函数是在基类中使用关键字 virtual 声明的函数。
虚函数允许子类重写它,从而在运行时通过基类指针或引用调用子类的重写版本,实现动态绑定。
我们想要的是在程序中任意点可以根据所调用的对象类型来选择调用的函数,这种操作被称为动态链接,或后期绑定。
特点:
- 在基类中可以有实现。通常虚函数在基类中提供默认实现,但子类可以选择重写。
- 动态绑定:在运行时根据对象的实际类型调用相应的函数版本。
- 可选重写:派生类可以选择性地重写虚函数,但不是必须。
纯虚函数是没有实现的虚函数,在基类中用 = 0 来声明。
在多态中,通常父类中虚函教的实现是毫无意义的,主要都是调用子类重写的内容因此可以将虚函救改为纯虚函数
纯虚函教语法:
当类中有了纯虚函数,这个类也称为抽象类
抽象类特点:
无法实例化对象
子类必须量写抽象类中的纯虚函数,否则也属于抽象类