在 C++ 中隐藏实现细节
Hiding Implementation Details in C++
我想从 header 中定义的接口中隐藏特定于实现的细节,以便代码易于维护并且在进行更新时可以更快地编译(尽管我没有后者的统计信息)。
但是,我不能使用动态内存或 2003 年以后的 c++(2017 年 11 月 14 日之后)。我也不能使用像 boost 这样的库。该应用程序是 real-time 嵌入式,因此效率很重要。有问题的代码与硬件紧密耦合。
我在这里查看了几篇建议使用 PIMPL 惯用语的帖子,但是间接寻址和动态内存似乎禁止这样做。一种选择是预分配 类 并设置指针,但这似乎不灵活。
下面是一个在实现文件中只使用函数和静态变量的简单示例;是否存在与封装或编译过程相关的问题?鉴于限制,我还能如何实现上述目标?
header 中的详细示例:
#ifndef HARDWARE_IF_HPP
#define HARDWARE_IF_HPP
class hardware_if
{
public:
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
private:
void hardware_if_standby();
void hardware_if_enable();
void hardware_if_disable();
static const uint32_t CONTROL_REGISTER = 0x10000000;
static const uint32_t ENABLED_MODE = 2;
static const uint32_t DISABLED_MODE = 3;
};
#endif
// CPP
#include <cstdio>
#include <stdint.h>
#include "hardware_if.hpp"
void hardware_if::hardware_if_standby()
{
printf("set hardware into standby state; write %X to 0x%X\n",
STANDBY_MODE, CONTROL_REGISTER);
}
void hardware_if::hardware_if_enable()
{
printf("set hardware into enabled state; write %X to 0x%X\n",
ENABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::hardware_if_disable()
{
printf("set hardware into disabled state; write %X to 0x%X\n",
DISABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::configure(cfg_mode mode)
{
switch (mode)
{
case standby:
hardware_if_standby();
break;
case enable:
hardware_if_enable();
break;
default:
hardware_if_disable();
break;
}
}
//
#include <stdint.h>
#include "hardware_if.hpp"
int main()
{
hardware_if hdw;
hdw.configure(hardware_if::enable);
return 0;
}
实施细节示例:
#ifndef HARDWARE_IF_HPP
#define HARDWARE_IF_HPP
class hardware_if
{
public:
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
};
#endif
// CPP
#include <cstdio>
#include <stdint.h>
#include "hardware_if.hpp"
static const uint32_t CONTROL_REGISTER = 0x10000000;
static const uint32_t STANDBY_MODE = 1;
static const uint32_t ENABLED_MODE = 2;
static const uint32_t DISABLED_MODE = 3;
void hardware_if_standby();
void hardware_if_enable();
void hardware_if_disable();
void hardware_if_standby()
{
printf("set hardware into standby state; write %X to 0x%X\n",
STANDBY_MODE, CONTROL_REGISTER);
}
void hardware_if_enable()
{
printf("set hardware into enabled state; write %X to 0x%X\n",
ENABLED_MODE, CONTROL_REGISTER);
}
void hardware_if_disable()
{
printf("set hardware into disabled state; write %X to 0x%X\n",
DISABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::configure(cfg_mode mode)
{
switch (mode)
{
case standby:
hardware_if_standby();
break;
case enable:
hardware_if_enable();
break;
default:
hardware_if_disable();
break;
}
}
//
#include <stdint.h>
#include "hardware_if.hpp"
int main()
{
hardware_if hdw;
hdw.configure(hardware_if::enable);
return 0;
}
您的特定示例 class 没有任何要隐藏的数据成员。私有静态数据成员可以安全地移动到 .cxx
文件中的一个未命名的命名空间中,这同样适用于 non-public 成员函数。
但这里有一个如何在没有内存分配的情况下隐藏数据成员的例子:
// hardware_if.h
class hardware_if
{
public:
hardware_if();
~hardware_if();
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
struct Impl;
private:
hardware_if(hardware_if const&);
hardware_if& operator=(hardware_if const&);
enum { IMPL_SIZE = 16 };
union {
unsigned char storage[IMPL_SIZE];
double align;
};
};
// hardware_if.cxx
#include <new>
struct hardware_if::Impl {
// The data members.
int a, b, c, d;
};
namespace {
const uint32_t CONTROL_REGISTER = 0x10000000;
const uint32_t ENABLED_MODE = 2;
const uint32_t DISABLED_MODE = 3;
void hardware_if_standby(hardware_if::Impl&) { /* ... */ }
void hardware_if_enable(hardware_if::Impl&) { /* ... */ }
void hardware_if_disable(hardware_if::Impl&) { /* ... */ }
// Compiler error if IMPL_SIZE != sizeof(hardware_if::Impl).
inline hardware_if::Impl& get_impl(unsigned char(&storage)[sizeof(hardware_if::Impl)]) {
return reinterpret_cast<hardware_if::Impl&>(storage);
}
}
hardware_if::hardware_if() {
new (storage) Impl;
}
hardware_if::~hardware_if() {
get_impl(storage).~Impl();
}
void hardware_if::configure(cfg_mode mode) {
Impl& impl = get_impl(storage);
switch(mode) {
case standby:
return hardware_if_standby(impl);
// ...
default:
break;
}
}
我想从 header 中定义的接口中隐藏特定于实现的细节,以便代码易于维护并且在进行更新时可以更快地编译(尽管我没有后者的统计信息)。
但是,我不能使用动态内存或 2003 年以后的 c++(2017 年 11 月 14 日之后)。我也不能使用像 boost 这样的库。该应用程序是 real-time 嵌入式,因此效率很重要。有问题的代码与硬件紧密耦合。
我在这里查看了几篇建议使用 PIMPL 惯用语的帖子,但是间接寻址和动态内存似乎禁止这样做。一种选择是预分配 类 并设置指针,但这似乎不灵活。
下面是一个在实现文件中只使用函数和静态变量的简单示例;是否存在与封装或编译过程相关的问题?鉴于限制,我还能如何实现上述目标?
header 中的详细示例:
#ifndef HARDWARE_IF_HPP
#define HARDWARE_IF_HPP
class hardware_if
{
public:
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
private:
void hardware_if_standby();
void hardware_if_enable();
void hardware_if_disable();
static const uint32_t CONTROL_REGISTER = 0x10000000;
static const uint32_t ENABLED_MODE = 2;
static const uint32_t DISABLED_MODE = 3;
};
#endif
// CPP
#include <cstdio>
#include <stdint.h>
#include "hardware_if.hpp"
void hardware_if::hardware_if_standby()
{
printf("set hardware into standby state; write %X to 0x%X\n",
STANDBY_MODE, CONTROL_REGISTER);
}
void hardware_if::hardware_if_enable()
{
printf("set hardware into enabled state; write %X to 0x%X\n",
ENABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::hardware_if_disable()
{
printf("set hardware into disabled state; write %X to 0x%X\n",
DISABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::configure(cfg_mode mode)
{
switch (mode)
{
case standby:
hardware_if_standby();
break;
case enable:
hardware_if_enable();
break;
default:
hardware_if_disable();
break;
}
}
//
#include <stdint.h>
#include "hardware_if.hpp"
int main()
{
hardware_if hdw;
hdw.configure(hardware_if::enable);
return 0;
}
实施细节示例:
#ifndef HARDWARE_IF_HPP
#define HARDWARE_IF_HPP
class hardware_if
{
public:
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
};
#endif
// CPP
#include <cstdio>
#include <stdint.h>
#include "hardware_if.hpp"
static const uint32_t CONTROL_REGISTER = 0x10000000;
static const uint32_t STANDBY_MODE = 1;
static const uint32_t ENABLED_MODE = 2;
static const uint32_t DISABLED_MODE = 3;
void hardware_if_standby();
void hardware_if_enable();
void hardware_if_disable();
void hardware_if_standby()
{
printf("set hardware into standby state; write %X to 0x%X\n",
STANDBY_MODE, CONTROL_REGISTER);
}
void hardware_if_enable()
{
printf("set hardware into enabled state; write %X to 0x%X\n",
ENABLED_MODE, CONTROL_REGISTER);
}
void hardware_if_disable()
{
printf("set hardware into disabled state; write %X to 0x%X\n",
DISABLED_MODE, CONTROL_REGISTER);
}
void hardware_if::configure(cfg_mode mode)
{
switch (mode)
{
case standby:
hardware_if_standby();
break;
case enable:
hardware_if_enable();
break;
default:
hardware_if_disable();
break;
}
}
//
#include <stdint.h>
#include "hardware_if.hpp"
int main()
{
hardware_if hdw;
hdw.configure(hardware_if::enable);
return 0;
}
您的特定示例 class 没有任何要隐藏的数据成员。私有静态数据成员可以安全地移动到 .cxx
文件中的一个未命名的命名空间中,这同样适用于 non-public 成员函数。
但这里有一个如何在没有内存分配的情况下隐藏数据成员的例子:
// hardware_if.h
class hardware_if
{
public:
hardware_if();
~hardware_if();
enum cfg_mode { standby, enable, disable };
void configure(cfg_mode mode);
struct Impl;
private:
hardware_if(hardware_if const&);
hardware_if& operator=(hardware_if const&);
enum { IMPL_SIZE = 16 };
union {
unsigned char storage[IMPL_SIZE];
double align;
};
};
// hardware_if.cxx
#include <new>
struct hardware_if::Impl {
// The data members.
int a, b, c, d;
};
namespace {
const uint32_t CONTROL_REGISTER = 0x10000000;
const uint32_t ENABLED_MODE = 2;
const uint32_t DISABLED_MODE = 3;
void hardware_if_standby(hardware_if::Impl&) { /* ... */ }
void hardware_if_enable(hardware_if::Impl&) { /* ... */ }
void hardware_if_disable(hardware_if::Impl&) { /* ... */ }
// Compiler error if IMPL_SIZE != sizeof(hardware_if::Impl).
inline hardware_if::Impl& get_impl(unsigned char(&storage)[sizeof(hardware_if::Impl)]) {
return reinterpret_cast<hardware_if::Impl&>(storage);
}
}
hardware_if::hardware_if() {
new (storage) Impl;
}
hardware_if::~hardware_if() {
get_impl(storage).~Impl();
}
void hardware_if::configure(cfg_mode mode) {
Impl& impl = get_impl(storage);
switch(mode) {
case standby:
return hardware_if_standby(impl);
// ...
default:
break;
}
}