在C++中,成员函数是一种非常强大的工具,可以显著提高代码的可读性、可维护性和复用性。在本文中,我们将介绍如何使用成员函数来实现代码复用,并提供一些实例来演示如何使用它们。
什么是成员函数?
在C++中,成员函数是属于一个类的函数。这些函数被绑定到一个类的实例,并且只能在该实例上调用。成员函数可以访问类的成员变量和其他成员函数,但不能访问其他具有局部作用域的变量。
使用成员函数的好处:
成员函数可以访问类的私有成员变量和方法,从而提高了代码的安全性和可读性。
成员函数可以在一个类中实现多个实例的相同行为,从而减少了代码重复。
成员函数可以更容易地将代码分离为模块,从而增加了代码的可维护性。
成员函数可以更容易地实现代码的封装,从而提高了代码的可复用性。
让我们看看如何使用成员函数来实现代码复用。
封装数据和行为
成员函数最常见的用途之一是将数据和行为封装在一个对象中。例如,假设我们要编写一个代表一个简单的计时器的类。该类可以有一个私有变量,其存储计时器的当前时间,并且可以有一些公共方法,用于启动、停止、暂停和重新开始计时器。
class Timer {
private:
int _time;
public:
void start();
void stop();
void pause();
void resume();
};
这里,_time是一个私有变量,表示计时器的当前时间。start,stop,pause和 resume是公共方法,该方法对 _time 进行操作以启动、停止、暂停和重新开始计时器。
假设我们想要扩展 Timer 类以计算计时器过去了多长时间。我们可以添加一个公共方法 getElapsedTime,该方法将返回当前时间与上次启动计时器的时间之间的差异。然而,这将要求我们在 start 方法中存储当前时间,在 getElapsedTime 方法中计算时间差异并在静态时期中存储上次启动时间。
为了避免重复编写代码并提高代码复用性,我们可以创建一个私有方法,calcElapsedTime,该方法将计算时间差异。然后,我们可以在 start 方法中调用该方法,以便在启动计时器时存储当前时间和上次启动时间。然后,我们可以在 getElapsedTime 方法中调用 calcElapsedTime 方法,并返回时间差异:
class Timer {
private:
int _time;
int _last_start_time;
void calcElapsedTime();
public:
void start();
void stop();
void pause();
void resume();
int getElapsedTime();
};
void Timer::start() {
calcElapsedTime();
_last_start_time = _time;
// ...
}
int Timer::getElapsedTime() {
calcElapsedTime();
return _time - _last_start_time;
}
void Timer::calcElapsedTime() {
// calculate elapsed time
}
这里,calcElapsedTime 是一个私有方法,该方法根据上次启动时间和当前时间计算时间差异。在 start 和 getElapsedTime 方法中都调用了这个方法,以确保我们在这两种情况下都计算了时间差异。这使得代码更加可读、易于维护,并且减少了代码复制和粘贴。
在多个类之间共享代码
另一个使用成员函数的常见场景是在多个类之间共享代码。例如,假设我们正在开发一个游戏,并且需要在多个类中实现相同的运动行为。我们可以为每个类编写一个相同的方法,并在每个类中实现该方法,但这将会导致大量的重复代码,并且可能导致维护问题。
相反,我们可以创建一个名为 move 的成员函数,并将该函数添加到每个类中。该函数将在这些类之间共享,从而避免了重复的代码,并提高了代码的可维护性。
class Movable {
public:
virtual void move() = 0;
};
class Player : public Movable {
public:
void move() { /* move player */ }
};
class Enemy : public Movable {
public:
void move() { /* move enemy */ }
};
这里,Movable 是一个抽象类,其定义了一个纯虚方法 move。Player 和 Enemy 是具体类,它们实现了 move 方法,以指定它们在游戏中的运动行为。
这种方法的好处是,我们可以将任何实现了 move 方法的类添加到 Movable 类型的容器中,并调用它们的 move 方法,以在游戏中移动它们。这样,我们可以减少代码复制和粘贴,并提高代码的可读性和可维护性。
封装对象的状态
成员函数还可以用于封装对象的状态。假设我们正在编写一个用于存储地址的类 Address。该类可以有两个私有变量,一个表示地址的行,另一个表示地址的列。我们可以编写一些公共方法,用于设置和获取地址的行和列,但这会导致公共接口中有太多的方法。
相反,我们可以创建一个名为 set 的成员函数,并将其添加到 Address 类中。该函数将接受一个包含行和列的结构体,并设置 Address 的行和列。
struct Point {
int x;
int y;
};
class Address {
private:
int _row;
int _col;
public:
void set(Point p) {
_row = p.x;
_col = p.y;
}
};
这里,Address 类只由一个成员函数 set 组成。该函数接受一个包含行和列的结构体,并将其用于设置地址的行和列。这样,我们可以将 setAddress 方法替换为 set,以更好地封装 Address 对象的状态,并提高代码的可读性和可维护性。
总结
使用成员函数可以显著提高代码的可读性、可维护性和复用性。它们可以封装数据和行为、在多个类之间共享代码,以及封装对象的状态。我们可以使用这些技术来使代码更加模块化、可测试、可重用,并提高我们的开发效率。