【Day26】:从struct进化成class的物件导向技巧(下)

建构子

建构子(constructor)是一种初始化类别物件的成员函式,每一种类别都有一个建构子,当宣告时如果没有定义建构子,则程序会自动提供一个没有任何程序叙述及参数的预设建构子(Default Constructor)。
建构子具有以下三个特性,如下:

  1. 建构子的名称与类别名称相同,例如类别名称为Car,则建构子为Car()。
  2. 不须指定回传型态,因为建构子没有回传值。
  3. 建构子可以有多载功能,也就是一个类别内可以存在多个相同名称,但参数列不同的建构子。

建构子是相当好用的技巧,用於类别的初始化,是个相当好用的技巧

底下就来介绍几个我实际使用时的情况吧

class Servo {
private:
	TIM_HandleTypeDef *timer;
	int channel;
	int angle;
public:
	Servo(TIM_HandleTypeDef *t, int c);
	void set_angle(double angle);
};

Servo::Servo(TIM_HandleTypeDef *t, int c) {
	timer = t;
	channel = c;
}

大家一看就知道这是一个伺服马达的类别吧,伺服马达的控制很简单,就是输出PWM。而不同PWM要输出到不同Timer的不同频道,因此这一个类别就要有两个变数,指标变数timer和整数变数channel,而由於这两个参数不应该被改动,因此我将其设定为private。
而当一宣告Servo这个变数的时候,就要传入两个参数,一个是timer的结构变数,另外该PWM输出是哪一个channel的,而在建构子函数我们就将传进来的两个参数储存到timer与channel变数中。宣告方式如下:

Servo servo1(&htim3, 3);

由於我们只着重在建构子的使用,因此set_angle()这个成员函式我们就不多做介绍了。
我们完全可以不设计建构子,但只要你建立了一个建构子,那程序就不会再帮你产生一个不做任何事的建构子,因此在宣告变数的时候就一定要传入参数。以上面Servo为例,我们就一定要传入两个参数,不可以用以下的方式来宣告

Servo servo1;

多型(Polymorphism)

这也是C++相当好用的一个功能之一。实际上多型的用法相当复杂,我们先只介绍最基本的用法。「多型」的精神在於,可以宣告相同名称,但不同功能的成员函式。一样以我实际使用的方式来介绍吧~

class Car {
private:
	double l1, l2;
public:
	double x;
	double y;
	Car();
	void move(double vx, double vy, double w0);
	void move(int dir, double dist);
	void stop();
};

我先说明一下,我想达到两种移动车子的方式,首先第一种是,给x、y、w0分别代表x分量速度、y分量速度、旋转角速度,让车子以这样的方式移动。第二种移动车子的方式是给予一个方向,并让车子以这个方向移动一段距离。
我们就可以以同样的名称来宣告函式,只是参数列不同,让整个程序的阅读又更值观了。
这里的重点在於可以以相同的名称来宣告函数,而如何实作出这两个函式就不在本篇教学的范围罗

小结

今天我们又讲解了两个物件导向重要的观念与小技巧,当然「物件导向」是相当巨大的一个观念,不太可能靠我们这两天的介绍就介绍完,我们只介绍几个写程序时很实用,也让程序更好阅读的方法。


<<:  【Day25】:从struct进化成class的物件导向技巧(上)

>>:  【Day27】:STM32实际应用1—马达精准控速(PID初浅教学(上))

24 - 建立结构化的 Log (2/4) - Elasticsearch Ingest Pipeline 资料 Index 前的转换好帮手 - 基本介绍

建立结构化的 Log 系列文章 (1/4) - Elastic Common Schema 结构化 ...

Day-25 事件机制(1)

在网页中的JavaScript程序码,必须经由事件触发(如:按下按钮,又称事件驱动event-dri...

[Day3] 经典时间序列预测方法盘点

第一篇记录了时间序列属性,将趋势、季节性等元素拆解、分别画出图表; 第二篇则介绍时间序列转换方法,透...

《从前一天整理行李,进行三重观点叠加》

一天始於前一天的30分钟。 回应生活来说, 就像我们会在重要日子的前一晚 确认充足,好好准备。 隔天...