谈及运算,我们总是习惯“数”的运算。而实际上,像时间之类的对象也是可以进行加减运算的。再进一步,我们的思维还可以拓展,运算加以加到任何事物上,只要我们可以为这些“运算”设计好意义。

  例如:有班级类和学生类。两个学生相加,组成了一个由两个学生构成的班级;班级加学生,代表班级增加了一名新同学;学生乘学生,结果为这两个学生“结对子”,可以做某些事(这个对子,需要定义成一个新的类);班级乘班级,是班级中的所有学生,两两结对子的所以可能组合。

  实际上,班级和学生,已经初步具备了数据库中用“学生表”存储学生信息的特征。一张“学生表”代表一个班级,而这张表中的每一条“记录”,则是具体的学生对象。

  利用数据库技术可以建立这张表格,可以用操纵数据库的语言(SQL语言),完成对数据的相关处理。

  这些处理,建立在数据库理论基础上。对于关系型数据库(前述“学生表”,按术语讲,就是一个“关系”),其基础是“关系代数”。关系代数,实际上就是定义了一组运算。无论这些运算用什么样的符号,可以与C++中重载后的运算符建立起联系来,让我们一起体会一下,若用C++去实现数据库最底层的运算,将可以采取什么样的策略。

  更深一层,代数系统就是由一个非空集合和一组运算构成的系统。这是任何计算模型(计算模型可以是通用的模型,更多我们强调的就是解决具体问题的计算模式),在本质上的描述。关系代数,只不过也就是代数系统中的一个例子罢了。

  所以,有机会“科班”学习计算机的同学,随着课程的进展,借助离散数学(代数系统是这门课程中的一部分)、可计算性理论等,体会从最一般的、抽象的层面看待计算,这是形成专业思维的重要部分。

  当然,在学习C++的时候,体会到“万物皆对象,各种操作皆运算”,摆脱运算一定是施加于“数”上的观念,可以有助于将未来要学习的抽象理论具体起来。大学的学习,达到理论联系实际很有必要。为此,本文的目标,就是让菜鸟在接触专业理论之前,至少隔着门缝看了一眼。

  下面的代码来点干货,学生加学生的运算,可以这样实现:

#include <iostream>
using namespace std;
class Student;
class Class //班级类
{
int number;
Student *students;
friend class Student;
public:
Class();
Class(const Class &c);
void display();
};

class Student //学僧类
{
private:
int num;
string name;
char sex;
int age;
friend class Class;
public:
Student(){}
Student(int n, string nam, char s, int a);
Class operator+(Student &s1);
};

Class::Class():number(0),students(NULL) {}
Class::Class(const Class &c)
{
number=c.number;
students=new Student[number];
int i;
for(i=0;i<number;i++)
students[i]=c.students[i];
}
void Class::display()
{
int i;
for(i=0; i<number; i++)
{
cout<<i<<": "<<students[i].num<<", "<<students[i].name;
cout<<", "<<students[i].sex<<", "<<students[i].age<<endl;
}
}

Student::Student(int n, string nam, char s, int a):num(n), name(nam), sex(s),age(a) {}
Class Student::operator+(Student &s1)
{
Class c;
c.number=2;
c.students=new Student[c.number];
c.students[0]=*this;
c.students[1]=s1;
return c;
}

int main()
{
Student s1(1, "Zhang", 'f', 20), s2(2, "Li", 'm', 18);
Class c = s1+s2;
c.display();
return 0;
}

进一步的拓展(请感兴趣的读者作为实践题目):

定义了Student s1, s2; Class c1, c2; 后:

(1)你是否可以定义出支持c1+c2、c1+s1、c1-c2之类的运算?

(2)为s1*s2、s1*c1、c1*c2确定其含义,必要时增加新的类型定义,实现*运算符的重载?

(3)(更远的未来)参考关系代数中对除法的定义,实现c1/s1、c1/c2运算?