物以类聚,人以群分,在生活中,我们习惯将事物进行分类,在程序设计中也是可以引入分类的思想。
中国的12生肖可以将人分成不同的类型;
外国的12星座也是将人分成不同的类型;
按照财富的多少分高产、中产、低产,也是将人进行分类;
官员的九品等级也是将官员进行分类;
老虎也分为东北虎、华南虎,孟加拉虎等;
将日常生活中的思维习惯引入到程序设计中;
将需求中的概念直观的映射到解决方案中;
以模块为中心构建可复用的软件系统;
提高软件产品的可维护性和可扩展性;
类:指的是一类事物,是一个抽象的概念,比如高产、中产、低产;
对象:指的是某个类的具体实体,比如笔者就是低产这类人中的一个对象;
一个类又可以分成多个小类,比如人类是一个类,人类可以分成黄种人、白种人、黑种人等小类,黄种人还可以继续分类,如中国人、韩国人、日本人等。
把事物分类就是为了方便区分,分类一般是按照属性和行为来分的。
继承
从已存在的类中细分出来的类与原类之间具有继承关系;
继承的类,也叫做子类,拥有原类,也叫做父类的所有属性和行为;
如东北虎是从老虎这个类中细分出来的,东北虎具有老虎的所有属性和行为;
组合
一些类的存在依赖于其他的类,这种关系叫组合;
组合的类在某个局部行由其他的类组成;
比如电脑这个类,是由内存、主板、显示器、硬盘等东哥类组成的;
生物类(可细分成动物类和植物类)
生物类的属:有生命
动物类(继承于生物类类)
动物类的属性:有生命,可移动
动物类的行为:找事物
植物类(继承于生物类类)
植物类的属性:有生命,可生长
人类(继承于动物类)
人类的属性:有生命,可移动
人类的行为:找食物、睡觉、劳动
禽兽类(继承于动物类)
禽兽类的属性:有生命、可移动
禽兽类的行为:找食物、睡觉
- 类:生物{
- 属性:有生命
- }
-
- 类:动物继承生物{
- 属性:可移动
- 行为:找食物
- }
-
- 类:植物继承生物{
- 属性:可生长
- }
-
- 类:禽兽继承动物{
- 行为:睡觉
- }
-
- 类:人类继承动物{
- 行为:睡觉
- 行为:劳动
- }
- struct 生物{
- 属性:有生命
- }
-
- struct 动物:生物{
- 属性:可移动
- 行为:找食物
- }
-
- struct 植物:生物{
- 属性:可生长
- }
-
- struct 禽兽:动物{
- 行为:睡觉
- }
-
- struct 人类:动物{
- 行为:睡觉
- 行为:劳动
- }
- struct Biology
- {
- bool living;
- };
-
- struct Animal :Biology
- {
- bool movable;
- void findFood()
- {
- printf("I need food!\n");
- }
- };
-
- struct Plant :Biology
- {
- bool growable;
- };
-
- struct Beast :Animal
- {
- void sleep()
- {
- printf("I need sleep!\n");
- }
- };
-
- struct Human :Animal
- {
- void sleep()
- {
- printf("I need sleep!\n");
- }
- void work()
- {
- printf("I need work!\n");
- }
- };
当实用类的时候,不需要关心类的使用细节;
只有在创建类的时候,才需要考虑内部的实现细节;
所谓封装就是将类的实现细节封起来。
1、成员变量:用于表示类属性的变量
2、成员函数:用于表示类行为的函数
3、成员变量和成员函数的访问级别
public:成员变量和成员函数可以在类的内部和外界访问;
private:成员变量和成员函数只能在类的内部被访问;
比如:
一个女生的外貌就是公开的,自己和别人都看得到,这就是public;
但是女生的年龄别人是看不见的,只有自己知道,这就是private;
要想知道这个女生的年龄,那就得让这个女生自己告诉你才行。
程序实例1:公有属性(public)和私有属性(private)的访问
- #include
-
- struct Biology
- {
- bool living;
- };
-
- struct Animal :Biology
- {
- bool movable;
- void findFood()
- {
- printf("I need food!\n");
- }
- };
-
- struct Plant :Biology
- {
- bool growable;
- };
-
- struct Beast :Animal
- {
- void sleep()
- {
- printf("I need sleep!\n");
- }
- };
-
- struct Human :Animal
- {
- void sleep()
- {
- printf("I need sleep!\n");
- }
- void work()
- {
- printf("I need work!\n");
- }
- };
-
- struct Girl :Human
- {
- private: //私有属性
- int age;
- int weight;
-
- public://公有属性
- void print()
- {
- age = 22;
- weight = 48;
-
- printf("I'm %d years old.\n",age);
- printf("My weight is %d.\n", weight);
- }
- };
-
-
- struct Boy :Human
- {
- private://私有属性
- int height;
- int salary;
-
- public://公有属性
- int age;
- int weight;
-
- void print()
- {
- height = 175;
- salary = 10000;
-
- printf("My height is %d.\n", height);
- printf("My salary is %d.\n", salary);
- }
- };
-
- int main()
- {
- Girl g;//创建一个对象g,跟定义一个变量差不多
- Boy b;//创建一个对象b
-
- //g.age = 20; //不能直接给g.age赋值,因为女孩的年龄是私有变量,不对外公开
- g.print();//可以通过询问女孩,让女孩自己告诉你
-
-
- b.age = 30; //可以给b.age赋值,因为男生的年龄是公有变量
- b.print();//询问男孩的身高和收入
- return 0;
- }
输出结果:
- I'm 22 years old.
- My weight is 48.
- My height is 175.
- My salary is 10000.
类成员(包括成员变量和成员函数)的作用域都是在类的内部,外部无法直接访问;
类的成员函数可以直接访问成员变量和调用成员函数;
类的外部可以通过类变量(也就是对象)来访问public成员;
类成员的作用域与访问级别没有关系;
C++中用struct 定义的类,如果没有定义私有还是公有的属性,那么默认就是公有属性(public);
程序实例2:类成员作用域
- #include
-
- int i = 1; //定义一个全局变量i
-
- struct Test
- {
- private:
- int i; //在类里面定义一个私有变量i
-
- public:
- int j;//在类里面定义一个公有变量j
- int getI()
- {
- i = 3;
-
- return i;
- }
- };
-
-
- int main()
- {
- int i = 2; //定义一个局部变量i
-
- Test test;
-
- test.j = 4;
-
- printf("i = %d\n", i);//打印局部变量i
- printf("::i = %d\n", ::i); //打印全局变量i
- //printf("test.i = %d\n",test.i); //类对象不能访问私有变量i
- printf("test.j = %d\n", test.j); //类对象可以访问公有变量j
- printf("test.getI() = %d\n", test.getI());//通过类成员函数访问类的私有变量
- return 0;
- }
输出结果:
- i = 2
- ::i = 1
- test.j = 4
- test.getI() = 3
struct在C语言中是表示结构体的,但是经过不断地改进已经越来越不像结构体了,既然已经变味了那就变得彻底一点吧。C++中有个新的关键字class,专门用来定义类。
其实class关键字和struct关键字的用法基本是一样的,只有一点小差异:
在用struct定义类时,所有成员的默认访问级别是public;
在用class定义类时,所有成员的默认访问级别是private;
- struct A
- {
- int i; //默认是public
- int getI() //默认是public
- {
- return i;
- }
- };
-
- class B
- {
- int i; //默认是private
- int getI() //默认是private
- {
- return i;
- }
- };
程序实例3:struct定义类与class定义类对比
- #include
-
- struct A
- {
- int i; //默认是public
- int getI() //默认是public
- {
- return i;
- }
- };
-
- class B
- {
- int i; //默认是private
- int getI() //默认是private
- {
- return i;
- }
- };
-
-
- int main()
- {
- A a;
- B b;
-
- a.i = 4;//struct定义的类默认的是公有变量,可以直接访问
- printf("a.getI() = %d\n",a.getI());
-
- //b.i = 5;//class定义的类默认的是私有变量,不能直接访问
- //printf("b.getI() = %d\n", b.getI());
-
- return 0;
- }
提供setOperatior函数设置运算类型;
提供setParameter函数设置运算参数;
提供result函数进行运算:返回值表示运算的合法性,通过引用参数返回结果。
C++的类支持声明和实现分开操作,将类的实现和定义分开:
.h头文件中只有类的声明,包括成员变量和成员函数的声明;
.cpp源文件中完成类中成员函数的具体实现;
头文件Operator.h
- #pragma once
- class Operator
- {
- private:
- char mOp;
- double mP1;
- double mP2;
-
- public:
- bool setOperator(char op);
- void setParameter(double p1, double p2);
- bool result(double& r);
- };
源文件Operator.cpp
- #include "Operator.h"
- bool Operator::setOperator(char op)
- {
- bool ret = false;
-
- if ((op == '+') || (op == '-') || (op == '*') || (op == '/'))
- {
- ret = true;
-
- mOp = op;
- }
- else
- {
- mOp = '\0';
- }
-
- return ret;
- }
-
- void Operator::setParameter(double p1, double p2)
- {
- mP1 = p1;
- mP2 = p2;
- }
-
- bool Operator::result(double& r)
- {
- bool ret = true;
- switch (mOp)
- {
- case '/':
- if ((-0.000000001 < mP2) && (mP2 < 0.000000001))
- {
- ret = false;
- }
- else
- {
- r = mP1 / mP2;
- }
- break;
-
- case '+':
- r = mP1 + mP2;
- break;
-
- case '-':
- r = mP1 - mP2;
- break;
-
- case '*':
- r = mP1 * mP2;
- break;
-
- default:
- ret = false;
- break;
- }
-
- return ret;
- }
main函数中使用类
- #include
- #include "Operator.h"
-
-
- int main()
- {
- Operator op;
- double r = 0;
- op.setOperator('/');
- op.setParameter(5,3);
-
- if (op.result(r))
- {
- printf("r = %lf\n", r);
- }
- else
- {
- printf("calculate error\n");
- }
-
-
- return 0;
- }