01_类的概念和定义
01_类的概念和定义
上方视频是我在哔哩哔哩上的视频,讲解 怎么写一个简单的c++类 可以看看
一、类的基本概念
在 C++ 中,类是一种用户自定义的数据类型,它将数据(成员变量)和操作这些数据的函数(成员函数)封装在一起。类是面向对象编程(OOP)的核心概念之一,它提供了一种将数据和行为捆绑在一起的方式,并允许通过访问控制对数据进行保护。
类与对象的关系
类就像是一个蓝图或模板,它定义了一类对象的共同属性和行为。而对象则是类的实例,是根据类这个蓝图创建出来的具体实体。例如,我们可以定义一个 Person
类,然后根据这个类创建出像 “张三”、“李四” 这样的具体对象。
二、类的定义语法
在 C++ 中,类的定义以关键字 class
开头,后面跟着类的名称,然后是一对花括号 {}
,花括号内包含类的成员(成员变量和成员函数),最后以分号 ;
结束。
下面是一个简单的 Person
类的定义示例:
class Person {
private:// 私有成员变量std::string name; // 姓名int age; // 年龄public:// 公有成员函数// 默认构造函数Person() {name = "Unknown";age = 0;}// 带参数的构造函数Person(const std::string& n, int a) {name = n;age = a;}// 获取姓名std::string getName() const {return name;}// 获取年龄int getAge() const {return age;}// 设置年龄void setAge(int a) {if (a >= 0) {age = a;}}// 显示信息void displayInfo() const {std::cout << "Name: " << name << ", Age: " << age << std::endl;}
};
访问控制修饰符
在上面的示例中,我们看到了 private
和 public
这两个访问控制修饰符:
- private:私有成员只能在类的内部访问,外部无法直接访问。私有成员通常用于隐藏类的实现细节,保护数据不被随意修改。
- public:公有成员可以在类的外部访问,通常用于提供类的接口,让外部代码可以与类进行交互。
- protected:保护成员与私有成员类似,但在继承关系中,子类可以访问父类的保护成员。
三、对象的创建和使用
定义了类之后,就可以创建该类的对象并使用对象的成员了。下面是一个使用 Person
类的示例:
#include <iostream>
#include <string>int main() {// 创建 Person 对象Person person1; // 使用默认构造函数Person person2("Alice", 25); // 使用带参数的构造函数// 访问公有成员函数std::cout << "Person 1: ";person1.displayInfo(); // 输出: Name: Unknown, Age: 0std::cout << "Person 2: ";person2.displayInfo(); // 输出: Name: Alice, Age: 25// 修改对象的属性person1.setAge(30);std::cout << "Person 1's new age: " << person1.getAge() << std::endl; // 输出: 30return 0;
}
构造函数
构造函数是一种特殊的成员函数,它在创建对象时自动调用,用于初始化对象的状态。构造函数的名称必须与类名相同,并且没有返回类型。在上面的示例中,Person
类有两个构造函数:一个是默认构造函数,另一个是带参数的构造函数。
成员函数
成员函数是定义在类内部的函数,它们可以访问类的所有成员(包括私有成员)。成员函数可以在类的定义内部实现,也可以在类的外部实现。在类的外部实现成员函数时,需要使用作用域解析运算符 ::
。例如:
// 在类的外部实现成员函数
void Person::displayInfo() const {std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
四、类的封装
封装是面向对象编程的三大特性之一(另外两个是继承和多态)。封装的核心思想是将数据和操作数据的函数捆绑在一起,并通过访问控制来隐藏内部实现细节,只对外提供必要的接口。
在上面的 Person
类示例中,name
和 age
被声明为私有成员,外部代码无法直接访问它们。通过提供公有的 getName()
、getAge()
和 setAge()
等接口函数,外部代码可以间接地访问和修改这些私有成员,这样可以确保数据的完整性和安全性。例如,setAge()
函数中对年龄进行了有效性检查,防止设置无效的年龄值。
五、类的继承
继承是面向对象编程的另一个重要特性,它允许我们创建一个新的类(派生类),继承另一个已有类(基类)的属性和行为。通过继承,可以实现代码的复用和层次化的组织。
下面是一个简单的继承示例:
// 基类
class Animal {
protected:std::string name;public:Animal(const std::string& n) : name(n) {}void eat() const {std::cout << name << " is eating." << std::endl;}virtual void makeSound() const {std::cout << name << " makes a sound." << std::endl;}
};// 派生类
class Dog : public Animal {
public:Dog(const std::string& n) : Animal(n) {}void makeSound() const override {std::cout << name << " barks." << std::endl;}void fetch() const {std::cout << name << " is fetching a ball." << std::endl;}
};// 派生类
class Cat : public Animal {
public:Cat(const std::string& n) : Animal(n) {}void makeSound() const override {std::cout << name << " meows." << std::endl;}
};
在上面的示例中,Dog
和 Cat
类都继承自 Animal
类。它们继承了 Animal
类的 name
成员变量和 eat()
成员函数,并且各自重写了 makeSound()
函数以实现自己的行为。此外,Dog
类还添加了自己特有的 fetch()
函数。
六、类的多态
多态是面向对象编程的第三个重要特性,它允许我们通过基类的指针或引用来调用派生类的函数,从而实现运行时的动态绑定。多态的实现通常依赖于虚函数(virtual
关键字)。
下面是一个使用多态的示例:
int main() {Dog dog("Buddy");Cat cat("Whiskers");// 通过基类指针实现多态Animal* animal1 = &dog;Animal* animal2 = &cat;animal1->eat(); // 输出: Buddy is eating.animal1->makeSound(); // 输出: Buddy barks.animal2->eat(); // 输出: Whiskers is eating.animal2->makeSound(); // 输出: Whiskers meows.return 0;
}
在上面的示例中,Animal
类的 makeSound()
函数被声明为虚函数(virtual
),这样在运行时会根据对象的实际类型来调用相应的函数。通过基类指针 animal1
和 animal2
分别指向 Dog
和 Cat
对象,调用 makeSound()
函数时会动态绑定到实际对象的函数实现,从而实现了多态。
七、总结
C++ 中的类是一种强大的用户自定义数据类型,它将数据和操作数据的函数封装在一起,实现了面向对象编程的核心概念。通过类,我们可以实现数据的封装、继承和多态,从而构建出更加模块化、可复用和可维护的代码。掌握类的定义和使用是学习 C++ 编程的重要一步。