【发布时间】:2017-07-20 13:29:55
【问题描述】:
我正在设计一些类来访问和控制微控制器的外围设备(adc、端口、usart 等)。该设备只有几个(在某些情况下只有一个)每个外围设备的实例,所以我决定将每个外围设备表示为一个单态类。我的一个类的定义和用法是这样的:
usart.h
class usart {
public:
static void init() { /* initialize the peripheral */ }
static char read() { /* read a char from the input buffer */ }
static void write(char ch) { /* write a char to the output buffer */ }
// ... more member functions
};
main1.cpp
#include "usart.h"
int main()
{
usart::init();
char data;
while (true) {
data = usart::read();
usart::write(data);
}
}
但是上面定义 usart 类的方式并没有禁止用户做这样的事情:
main2.cpp
#include "usart.h"
int main()
{
// I don't want object construction
usart serial1;
usart serial2;
// neither assignment
serial1 = serial2;
// two objects representing the same hardware resource
// I don't want that
serial1.init();
serial2.write('r');
}
我知道从 C++11 开始我可以使用 delete 关键字来阻止编译器创建默认构造函数和函数,但我不知道编译器创建的这些默认值到底是什么。有复制构造函数、复制赋值、移动语义重载等。我需要在我的类上放置多少删除(以及在哪些函数和构造函数中)?
更新:我知道我可以(也许应该)使用命名空间而不是类,但我担心以后我需要将这些类(或命名空间)作为模板参数传递。 AFAIK 无法使用命名空间作为模板参数,因为我选择使用具有静态成员的类而不是命名空间。
【问题讨论】:
-
~usart() = delete;现在无法创建实例。 -
如果您打算没有实例 - 为什么要使用类?只需使用带有函数的命名空间。
-
简单,不要滥用类。
namespace usart { }. -
雅格尼。我已经处理了几种“单例”硬件(fpga、cpld、usart 等)恕我直言,您现在可以付出任何努力来防止不熟悉您的代码和系统的人在未来。他们犯的任何错误都不是你的错。让你的类使用简单、直接、易读。在我的嵌入式软件工作中,静态方法属性很少甚至不存在,静态数据属性仅限于“唯一 ID”计数器。我再说一遍,亚格尼。
-
其实我收回了。仅仅禁用一个析构函数仍然可以让一个人写
usart* p = new usart();(然后泄漏实例,因为他们无法销毁它)。但是,禁用默认构造函数(并且不提供任何其他构造函数)可以解决问题:usart() = delete;是的,编译器将生成复制构造函数等 - 但在复制实例之前,您需要创建一个实例来复制 来自,并且不会有构造函数。
标签: c++ c++11 design-patterns monostate