文章目录
- 类的介绍
-
类的声明 1.1 类名 1.2 成员变量 1.3 成员函数 1.4 访问权限
-
类的定义 2.1 成员变量的初始化 2.2 成员函数的实现
-
对象的创建和销毁 3.1 默认构造函数 3.2 析构函数 3.3 拷贝构造函数 3.4 对象的实例化 3.5 对象的销毁
-
成员访问控制 4.1 公有成员 4.2 私有成员 4.3 保护成员
-
类的封装性 5.1 封装的概念 5.2 封装的好处
前言
这篇文章主要主要介绍了c++类和对象的前半部分内容,包含类的声明,定义,对象的创建和销毁,成员的访问和控制,类的封装性。
类的介绍
c++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
类用于指定对象的形式,是一种用户自定义的数据类型,它是一种封装了数据和函数的组合。类中的数据称为成员变量,函数称为成员函数。类可以被看作是一种模板,可以用来创建具有相同属性和行为的多个对象。
一、类的声明
1、类名
类的声明通常包括类名和它的成员列表,但不包括成员函数的实际代码。类声明的基本语法如下:
class 类名;
这种声明被称为前向声明,它是必须的,尤其是当类A中用到了类B,而类B的声明出现在类A的后面时。前向声明只能作为指针或引用,不能定义类的对象,也就不能调用对象中的方法。
2、成员变量
成员变量(也称为属性或字段)是类中用于存储数据的变量。成员变量可以是任何数据类型,例如整数、浮点数、字符、字符串、甚至是其他对象。
class Person {
int age; // 整数类型的成员变量
std::string name; // 字符串类型的成员变量
};
3、成员函数
成员函数(也称为方法)是类中用于定义对象行为的函数。成员函数可以访问类的成员变量,并且可以对它们进行操作。
class Person {
int age;
std::string name;
public:
void setName(const std::string& newName) {
name = newName;
}
std::string getName() const {
return name;
}
};
4、访问权限
访问权限定义了类成员(包括成员变量和成员函数)的可见性。常见的访问权限有三种:`public`、`protected` 和 `private`。
public:成员在任何地方都可以访问。
protected:成员只能在类内部和派生类中访问。
private:成员只能在类内部访问。
class Person {
private:
int age;
std::string name;
public:
void setName(const std::string& newName) {
name = newName;
}
std::string getName() const {
return name;
}
protected:
// 保护成员
// ...
private:
// 私有成员
// ...
};
二、类的定义
定义一个类需要使用关键字 class,然后指定类的名称,并类的主体是包含在一对花括号中,主体包含类的成员变量和成员函数。
定义一个类,本质上是定义一个数据类型的蓝图,它定义了类的对象包括了什么,以及可以在这个对象上执行哪些操作。
以下实例我们使用关键字 class 定义 Box 数据类型,包含了三个成员变量 length、breadth 和 height:
class Box
{
public:
double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
};
关键字 public 确定了类成员的访问属性。在类对象作用域内,公共成员在类的外部是可访问的。也可以指定类的成员为 private 或 protected,这个我们稍后会进行讲解。
2.1 成员变量的初始化
在C++中,成员变量可以在构造函数中初始化,或者使用初始化列表来初始化。
class Person {
private:
int age;
std::string name;
public:
// 构造函数
Person(int initialAge, const std::string& initialName)
: age(initialAge), name(initialName) {}
// 其他成员函数
// ...
};
2.2 成员函数的实现
成员函数通常声明在类的声明中,但可以在类的外部实现。如果在类声明中直接实现了成员函数(称为内联函数),则该函数的定义也会出现在类声明中。
#include <iostream>
#include <string>
class Person {
private:
int age;
std::string name;
public:
Person(int initialAge, const std::string& initialName)
: age(initialAge), name(initialName) {}
void setName(const std::string& newName) {
name = newName;
}
std::string getName() const {
return name;
}
void display() const {
std::cout << "Name: " << name << ", Age: " << age << std::endl;
}
};
int main() {
Person person(25, "John Doe");
person.display();
return 0;
}
在这个例子中,`Person` 类有一个构造函数,用于初始化 `age` 和 `name` 成员变量。成员函数 `setName` 和 `getName` 用于设置和获取 `name` 成员变量的值。成员函数 `display` 用于打印 `Person` 对象的信息。
三、对象的创建和销毁
3.1 默认构造函数:
默认构造函数是一个类的特殊成员函数,当对象被创建时自动调用的函数。它没有任何参数,用于初始化对象的成员变量。如果一个类没有显式定义默认构造函数,编译器会自动生成一个默认构造函数。
下面是一个默认构造函数的代码示例:
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "Default constructor called" << std::endl;
}
};
int main() {
MyClass obj;
return 0;
}
在这个示例中,MyClass
类有一个默认构造函数。默认构造函数没有任何参数,并在创建对象时被调用。在main
函数中,我们创建了一个MyClass
对象obj
,并输出了一条消息来验证默认构造函数被调用。
#include <iostream>
class MyClass {
public:
MyClass() {
std::cout << "Default constructor called" << std::endl;
}
};
int main() {
MyClass obj;
return 0;
}
在这个示例中,MyClass
类有一个默认构造函数。默认构造函数没有任何参数,并在创建对象时被调用。在main
函数中,我们创建了一个MyClass
对象obj
,并输出了一条消息来验证默认构造函数被调用。
3.2 析构函数:
析构函数是一个类的特殊成员函数,用于在对象销毁时自动调用。它的名称与类名相同,但前面加上一个波浪号(~)。析构函数主要用来清理对象所占用的资源,如释放内存、关闭文件等。
析构函数没有参数,也没有返回值。当对象的作用域结束、程序执行完毕、delete运算符用于释放动态分配的对象内存时,析构函数会被自动调用。
比如在下面这个栈中:
3.3拷贝构造函数:
拷贝构造函数是一个特殊的构造函数,用于创建一个新的对象,该对象的内容是已有对象的一个副本,形式:(ClassName(const ClassName& obj));
拷贝构造函数可以自定义实现,或者使用编译器自动生成的默认拷贝构造函数(当类没有显式定义拷贝构造函数时,编译器会自动生成一个默认的拷贝构造函数,该函数执行的是浅拷贝)。如果类中存在指针或其他资源,通常需要自定义拷贝构造函数,实现深拷贝。
代码示例:
class MyClass {
public:
MyClass(); // 构造函数
MyClass(const MyClass& obj); // 拷贝构造函数
// 其他成员函数和成员变量
private:
int data;
};
MyClass::MyClass() {
// 构造函数的实现
}
MyClass::MyClass(const MyClass& obj) {
// 拷贝构造函数的实现
data = obj.data; // 执行深拷贝操作
}
3.4 对象的实例化:
在程序中创建一个对象称为对象的实例化。对象的实例化可以通过调用类的构造函数来完成。构造函数负责为对象的成员变量分配内存并进行初始化,从而创建对象的实例。
3.5 对象的销毁:
当对象不再被使用时,它会被销毁。对象的销毁可以通过调用类的析构函数来完成。析构函数主要用来释放对象占用的资源,清理对象的操作。对象销毁的时机通常是在对象超出其作用域、程序结束或者手动调用delete等情况下。
四、成员访问控制
4.1 公有成员:
公有成员是指在类中声明为public的成员。公有成员可以被任何地方的代码访问,包括类的内部和外部。这意味着其他类和对象可以直接访问和修改公有成员。
在这张图片中public:后面的就是公有成员,其他类和对象可以直接访问和修改。
4.2 私有成员:
私有成员是指在类中声明为private的成员。私有成员只能被同一个类的其他成员函数访问,不能被类的外部代码访问。私有成员用于实现类的封装,隐藏类的内部细节。
4.3 保护成员:
保护成员是指在类中声明为protected的成员。保护成员可以被同一个类的其他成员函数和派生类的成员函数访问,但不能被类的外部代码访问。保护成员提供了一种在继承关系中,子类可以访问父类的成员,但其他类不能访问的机制。
#include <iostream>
class Base {
protected:
int protectedData;
public:
Base() : protectedData(0) {}
void printProtectedData() {
std::cout << "Protected Data: " << protectedData << std::endl;
}
};
class Derived : public Base {
public:
void setProtectedData(int newData) {
protectedData = newData;
}
};
int main() {
Derived derivedObj;
derivedObj.setProtectedData(10);
derivedObj.printProtectedData();
return 0;
}
在这个例子中,Base
类中的 protectedData
是一个保护成员变量,只能在派生类中访问。Derived
类继承自 Base
类,并可以访问和修改 protectedData
。
在 main
函数中,我们创建了一个 Derived
类的对象 derivedObj
,并使用 setProtectedData
函数将 protectedData
设置为 10
。然后,我们调用 printProtectedData
函数来输出 protectedData
的值。
由于 protectedData
是一个保护成员变量,它不能在类的外部直接访问。只有派生类中的成员函数才能直接访问和修改它。因此,这个例子演示了如何使用保护成员来限制对类成员的访问。
五、类的封装性
5.1 封装的概念
封装是面向对象编程中的一种基本原则,它指的是将数据和处理数据的代码包装在一起,形成一个独立的单元。这个单元称为类。
5.2 封装的好处
封装有以下几个好处:
1. 数据隐藏:
封装可以隐藏对象的内部细节,只暴露出必要的接口给外部使用。这样可以防止外部代码直接访问对象的内部数据,提高了安全性和稳定性。
2. 代码复用:
封装将相关的数据和方法组织在一起,形成一个独立的类。这样可以方便地复用代码,提高开发效率。
3. 模块化设计:
封装让程序可以按照模块化的方式设计和构建。每个类都代表一个独立的模块,可以独立地开发、测试和维护。
4. 简化调用:
封装可以把复杂的逻辑处理封装在类的内部,对外提供简单的接口。这样使用者不需要了解内部的复杂实现,只需要调用接口即可。
5. 可维护性:
封装可以让代码更加可维护。因为内部数据和实现细节被封装起来,当需要修改时,只需要修改封装的类即可,不影响其他部分。
封装提供了一种清晰、安全、简洁和可维护的编程方式,使得面向对象编程更加灵活和高效。
总结
以上就是类和对象的前半部分,后续我会带来更多实用的内容,感兴趣的可以点个赞支持一下!