阿里妹导读:程序开发的时候经常会使用到接口。众所周知,C++语言层面并没有接口的概念,但并不意味着C++不能实现接口的功能。相反,正是由于C++语言没有提供标准的接口,导致实际实现接口的方法多种多样。那么C++有哪些实现接口的方法呢,不同的方法又适用于哪些场景呢?本文分享在C++接口工程实践上的一些探索心得。
文末福利:免费下载《计算机发展百年趣味史》电子书。
class Network
{
public:
bool send(const char* host,
uint16_t port,
const std::string& message);
}
class Network
{
public:
virtual bool send(const char* host,
uint16_t port,
const std::string& message) = 0;
static Network* New();
static void Delete(Network* network);
}
虚函数开销:虚函数调用需要使用虚函数表指针间接调用,运行时才能决定调用哪个函数,无法在编译链接期间内联优化。实际上调用接口在编译期间就能确定调用哪个函数,无需虚函数的动态特性。
二进制兼容:由于虚函数是按照索引查询虚函数表来调用,增加虚函数会造成索引变化,新接口不能在二进制层面兼容老接口,而且由于用户可能继承了Network接口类,在末尾增加虚函数也有风险,因此虚函数接口一经发布,难以修改。
class NetworkImpl;
class Network
{
public:
bool send(const char* host,
uint16_t port,
const std::string& message);
Network();
~Network();
private:
NetworkImpl* impl;
}
class Network
{
public:
bool send(const char* host,
uint16_t port,
const std::string& message);
static Network* New();
static void Delete(Network* network);
protected:
Network();
~Network();
}
class NetworkImpl : public Network
{
friend class Network;
private:
//Network类的成员变量
}
bool Network::send(const char* host,
uint16_t port,
const std::string& message)
{
NetworkImpl* impl = (NetworkImpl*)this;
//通过impl访问成员变量,实现Network
}
static Network* New()
{
return new NetworkImpl();
}
static void Delete(Network* network)
{
delete (NetworkImpl*)network;
}
class Network
{
public:
class Listener
{
public:
void onReceive(const std::string& message);
}
bool send(const char* host,
uint16_t port,
const std::string& message);
void registerListener(Listener* listener);
}
class Network
{
public:
class Listener
{
public:
virtual void onReceive(const std::string& message) = 0;
}
bool send(const char* host,
uint16_t port,
const std::string& message);
void registerListener(Listener* listener);
}
class Network
{
public:
typedef void (*OnReceive)(const std::string& message, void* arg);
bool send(const char* host,
uint16_t port,
const std::string& message);
void registerListener(OnReceive listener, void* arg);
}
class Network
{
public:
typedef std::function<void(const std::string& message)> OnReceive;
bool send(const char* host,
uint16_t port,
const std::string& message);
void registerListener(const OnReceive& listener);
}
class Network
{
public:
class Listener
{
public:
void onReceive(const std::string& message);
}
typedef void (Listener::* OnReceive)(const std::string& message);
bool send(const char* host,
uint16_t port,
const std::string& message);
void registerListener(Listener* listener, OnReceive method);
template<typename Class>
void registerListener(Class* listener,
void (Class::* method)(const std::string& message)
{
registerListener((Listener*)listener, (OnReceive)method);
}
}
class Serializable
{
public:
virtual void serialize(std::string& buffer) const = 0;
};
class Network
{
public:
bool send(const char* host,
uint16_t port,
const Serializable& s);
}
class IntSerializable : public Serializable
{
public:
IntSerializable(const int* i) :
intThis(i)
{
}
IntSerializable(const int& i) :
intThis(&i)
{
}
virtual void serialize(std::string& buffer) const override
{
buffer += std::to_string(*intThis);
}
private:
const int* const intThis;
};
Network* network = Network::New();
int i = 1;
network->send(ip, port, IntSerializable(i));