Виртуальный деструктор для наддува: некопируемые классы?
У меня есть вопрос по поводу следующего кода:
class MyClass : private boost::noncopyable
{
public:
MyClass() {}
virtual ~MyClass() {}
}
class OtherClass : private boost::noncopyable
{
private:
MyClass* m_pMyClass;
}
Я думаю, что MyClass не может быть скопирован с использованием конструкции или назначения. Использование виртуального деструктора необходимо, если я хочу поддерживать производные классы от MyClass, которые я не хочу поддерживать. Я не собираюсь создавать указатели на этот класс и передавать их.
Я не хочу Singleton, и я не вижу обратной стороны в удалении виртуального деструктора.
Вносить ли мне потенциальную проблему, если удалить виртуальный деструктор для некопируемого класса? Есть ли лучшие практики для обработки класса, который не обязательно должен быть Singleton, но я хочу только один экземпляр в другом классе и не поддерживать наследование?
5 ответов
Нет, весь смысл виртуального деструктора в том, что производные классы могут должным образом полиморфно разрушаться. Если это никогда не будет базовый класс, вам не нужно, чтобы он был виртуальным.
Общее правило: если у вашего класса есть виртуальные функции, ему нужен виртуальный деструктор. Если это не так, но все еще является производным от базового класса, базовый класс (и, следовательно, ваш класс) может зависеть или не нуждаться в виртуальном деструкторе в зависимости.
Извлечение вашего класса из boost::noncopyable
на самом деле не считается производным от базового класса. boost::noncopyable
больше похоже на удобную аннотацию, подкрепленную парой объявлений, которые заставят компилятор применять аннотацию. На самом деле это не базовый класс. Никто никогда не попытается передать указатель на ваш класс в качестве указателя или ссылки на boost::noncopyable
, И даже если бы они сделали ваш виртуальный деструктор не помог бы, потому что boost::noncopyable
деструктор
И, наконец, как было отмечено в комментарии, вы даже в частном порядке наследуете от boost::noncopyable
так что это даже не совсем наследство, если это касается кого-либо за пределами класса.
Так что на самом деле не нужно превращать его в виртуального деструктора.
Виртуальный деструктор в базовом классе используется, чтобы избежать проблемы частичного уничтожения, например:
Base *pBase = new Derived();
delete pBase;
//if destructor is not made virtual then derived class destructor will never called.
Когда вы наследуете класс конфиденциально, компилятор не будет выполнять неявное приведение из производного в базовый класс, и если вы уверены, что производный объект никогда не будет уничтожен с помощью указателя базового класса, вам не нужен виртуальный деструктор в базовом классе.
Base *pBase = new Derived(); // will flash error
Я действительно не фанат класса boost::noncopyable в целом. Почему бы просто не объявить конструктор копирования вашего класса и оператор присваивания закрытыми и не определять их. Это позволит сделать то же самое, и вы можете отказаться от виртуального деструктора.
Boost предоставляет только виртуальный деструктор, так что люди могут передавать полиморфные объекты boost::noncopyable и при этом вести себя хорошо. Технически говоря, если вы не собираетесь использовать класс полиморфно (вы даже можете наследовать его), вам действительно не нужен виртуальный деструктор.
boost::noncopyable
подразумевается, что вы не хотите делать копии объекта. Вы знаете, что это отличается от получения от объекта.
Совершенно хорошо избавиться от виртуального деструктора, если вы никогда не будете наследовать объект. Если вы хотите применить политику "не наследовать от этого объекта", есть способ. К сожалению, нет boost::nonderivable
чтобы сделать это для тебя.
Как упоминалось в ссылке, C++11 позволяет вам объявить класс final
:
class MyClass : final private boost::noncopyable { ... };