c ++ 11 — Как предотвратить создание компилятором C ++ любого члена класса по умолчанию?

Я разрабатываю несколько классов для доступа и управления периферийными устройствами микроконтроллера (АЦП, порт, USB и т. Д.). Устройство имеет всего несколько (в некоторых случаях только один) экземпляров каждого периферийного устройства, поэтому я решил представить каждое периферийное устройство в виде класса с одним состоянием. Определение и использование одного из моих классов будет примерно таким:

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 я могу использовать удалять ключевое слово, чтобы предотвратить создание компилятором конструкторов и функций по умолчанию, но я не знаю точно, что это за настройки по умолчанию, которые создает компилятор. Существуют конструкторы копирования, назначения копирования, перегрузки семантики перемещения и т. Д. Сколько удалятьs мне нужно поставить на мой класс (и в каких функциях и конструкторах)?

ОбновитьЯ знаю, что могу (и, возможно, должен) использовать пространства имен вместо классов, но, боюсь, позже мне нужно будет передать эти классы (или пространства имен) в качестве аргументов шаблона. AFAIK: невозможно использовать пространства имен в качестве аргументов шаблона, из-за этого я решил использовать классы со статическими членами вместо пространств имен.

1

Решение

struct cannot_exist {
cannot_exist()=delete;
~cannot_exist()=delete;
cannot_exist(cannot_exist const&)=delete;
cannot_exist(cannot_exist &&)=delete;
cannot_exist& operator=(cannot_exist const&)=delete;
cannot_exist& operator=(cannot_exist &&)=delete;
};

это класс с каждым членом, который C ++ генерирует для вас, явно удаленным. (Вы можете сделать это с меньшим количеством, но я не вижу смысла быть менее явным).

Просто наследовать от cannot_exist и … экземпляр вашего класса не может существовать, и при этом у него не будет никакой функции-члена, автоматически определяемой компилятором. Попытки вызвать их приведут к ошибкам компилятора.

Однако, если у вас есть класс, который не может существовать, рассмотрите возможность использования namespace,

class usart:cannot_exist {
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
};

против

namespace usart {
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
};
2

Другие решения

Я бы попробовал эти два способа

  1. Объявите чисто виртуальную функцию в классе. Это делает класс чисто виртуальным, поэтому его нельзя создать.

  2. Объявите конструктор по умолчанию как закрытую функцию-член. Таким образом, метод внешнего класса не может получить доступ к конструктору.

0

По вопросам рекламы [email protected]