面向对象和基于对象两种编程风格的区别

面向对象的编程风格会暴露抽象类,基于对象的编程风格不是暴露抽象类。

面向对象的编程风格会让用户定义一个类继承抽象类来重写虚函数,进而利用多态的特性实现回调。基于对象的编程风格会让用户定义一个类包含一个提供给用户的类(此类虽然不是抽象类,功能目的却和面向对象编程风格的抽象类一样),通过调用此类提供的设置回调函数的接口来处理用户需要此类内部调用的函数。

我们就以网络库中的 TcpServer 举例。

面向对象编程风格

EchoServer 继承 TcpServer 这个抽象类,用户重写提供的虚函数,从而利用多态调用派生类重写的虚函数(调用的过程这里没有实际写出来)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class TcpServer {
public:
TcpServer() = default;
virtual ~TcpServer() = default;

virtual void OnConnection() = 0;
virtual void OnMessage() = 0;
virtual void OnClose() = 0;
};

class EchoServer : public TcpServer {
public:
EchoServer() = default;
~EchoServer() = default;
// 重写
void OnConnection() {}
void OnMessage() {}
void OnClose() {}
};

基于对象编程风格

EchoServer 包含一个 TcpServer(具体类)对象,在构造函数中调用 TcpServer 对象提供的设置回调函数的接口,并结合 bind 注册如下三个回调函数,这三个回调函数的具体逻辑由用户自己实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class EchoServer {
public:
EchoServer() { // 设置回调
server.SetConnectionCallback(boost::bind(&EchoServer::OnConnection, this));
server.SetConnectionCallback(boost::bind(&EchoServer::OnMessage, this));
server.SetConnectionCallback(boost::bind(&EchoServer::OnClose, this));
}

void OnConnection() {}

void OnMessage() {}

void OnClose() {}

private:
TcpServer server; // TcpServer 是网络库已经封装的 TCP 服务器类
};