- 💭 写在前面:本章我们将进入 Object-oriented Programming,面向对象编程的讲解,探讨 C++ 中的类,继承等。
目录
0x00 面向对象编程
0x01 C语言中的结构体
0x02 案例研究:C++ 中的类
0x03 术语
0x04 继承:动机
0x05 继承和指针
0x00 面向对象编程
另一种重要的编程语言范式,编程是对象的创建和交互。
对象是相关数据和代码的集合,数据 = 属性 (字段) ,代码 = 方法 (函数)。
通常,对象对应于现实世界中的某物。
例如网站系统中的学生对象,网页浏览器引擎中的 HTML 元素对象。
许多现代编程语言在某种程度上支持面向对象编程的概念,例如:C++,Java,Python...
0x01 C语言中的结构体
让我们回顾一下C语言 (它不被认为采用面向对象编程)
struct 用于将一组数据定义为一种新类型,处理这种结构体的函数是单独定义的。
struct Student {int id;char name[32];...
};void printStudent(struct Student *x) {printf("ID: %d\n", x->id);...
}
0x02 案例研究:C++ 中的类
在 C++ 中,我们定义和使用类,将相关数据 (属性) 和代码 (方法) 绑定在一起。
这种类后来被用来创建对象 (实例),我们还使用访问修饰符 (public 和 private) 来隐藏内部细节,使其不被外部访问。
class Student {private:int id;string name;public:void Print() {cout << "ID: " << id << endl;cout << "Name: " << name << endl;}...
};
0x03 术语
封装 (Encapsulation) :将相关数据和代码绑定在一起
抽象 (Abstraction) / 信息隐藏 (info hiding):仅暴露必要信息,省略实现细节
我们将学生定义为支持 Print() 等功能的对象,我们使内部细节无法从外部访问。
class Student {private:int id;string name;public:void Print() {cout << "ID: " << id << endl;cout << "Name: " << name << endl;}...
};
0x04 继承:动机
假设我们要开发学生管理系统,让我们定义 Student 和 Professor 类如下 (注意这次我们为学生添加了 GPA 属性),这两个类共享一些属性和方法。
class Student {
private:int id;string name;double GPA; // Grade Point
public:int GetID() { return id; }string GetName() { return name; }double GetGPA() { return GPA; }void Print() { ... }
};class Professor {
private:int id;string name;string office; // Office room No.
public:int GetID() { return id; }string GetName() { return name; }string GetOffice() { return office; }void Print() { ... }
};
然后,这两个类的对象必须分别存储和处理,在下面的示例中,我们必须有单独的数组 (students 和 profs) 和函数 (printStudents 和 printProfs) 。
void printStudents(Student* students[]) { ... }
void printProfs(Professor* profs[]) { ... }
int main() {Student* students[MAX_N] = { NULL };Professor* profs[MAX_N] = { NULL };students[0] = new Student(...);profs[0] = new Professor(...);...printStudents(students);printProfs(profs);return 0;
}
相反,我们可以从这两个类中提取共同特征,并将其定义为 UnivMem 类,然后,Student 和Professor 类将继承这个类。目前,假设只有UnivMem类具有 Print() 方法。
class UnivMem {
private:int id;string name;
public:int GetID() { return id; }string GetName() { return name; }void Print() { ... }
};class Student : public UnivMem {
private:double GPA;
public:double GetGPA() { return GPA; }
};class Professor : public UnivMem {
private:string office;
public:string GetOffice() { return office; }
};
现在,UnivMem 指针可以指向 Student 或 Professor 对象,隐式上转型为 UnivMem 指针,直观上,这很合理,因为 Student 是 UnivMem 的一种。
void printMembers(UnivMem* mems[]) {for (int i = 0; mems[i] != NULL; i++)mems[i]->Print();
}
int main() {UnivMem* members[MAX_N] = { NULL };members[0] = new Student(...);members[1] = new Professor(...);printMembers(members);return 0;
}
0x05 继承和指针
如果我们使用一个 Student 指针,我们可以访问对象的所有公共属性和方法,请注意下面的图表仅为概念说明(实际上,方法不存储在对象内存中),此图中不包括私有属性。
与此同时,如果我们使用一个 UnivMem 指针,我们只能访问 UnivMem 类中的公共属性和方法, 即使实际上被这个 UnivMem 指针指向的对象是一个 Student 对象,我们也不能调用 GetGPA() 方法。
在这个例子中,只有第一个调用 s->GetGPA() 会成功编译和运行。
即使 m1 实际上指向一个 Student 对象,m1->GetGPA() 也不会编译通过。
int main() {UnivMem* m1, * m2;Student* s = new Student(...);Professor* p = new Professor(...);m1 = s;m2 = p;cout << s->GetGPA() << endl; // OKcout << p->GetGPA() << endl; // Errorcout << m1->GetGPA() << endl; // Errorcout << m2->GetGPA() << endl; // Errorreturn 0;
}
📌 [ 笔者 ] 王亦优
📃 [ 更新 ] 2024.6.10
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,本人也很想知道这些错误,恳望读者批评指正!
📜 参考资料 C++reference[EB/OL]. []. http://www.cplusplus.com/reference/. Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. . |