Итак, все говорят, что вы не можете это сделать - это ведет к неопределенному поведению. тем не мение
Есть несколько случаев, когда это безопасно. Если вы никогда не создаете экземпляры своего класса динамически, тогда все должно быть в порядке. (т.е. нет новых вызовов)
Тем не менее, это обычно считается плохой вещью, поскольку кто-то может попытаться создать ее полиморфно в более поздний срок. (Вы можете быть в состоянии защититься от этого с помощью нового нереализованного частного оператора, но я не уверен.)
У меня есть два примера, в которых я не ненавижу выводить из классов с не виртуальными деструкторами.
Первый - создание синтаксического сахара с использованием временных ... вот надуманный пример.
class MyList : public std::vector<int>
{
public:
MyList operator<<(int i) const
{
MyList retval(*this);
retval.push_back(i);
return retval;
}
private:
// Prevent heap allocation
void * operator new (size_t);
void * operator new[] (size_t);
void operator delete (void *);
void operator delete[] (void*);
};
void do_somthing_with_a_vec( std::vector<int> v );
void do_somthing_with_a_const_vec_ref( const std::vector<int> &v );
int main()
{
// I think this slices correctly ..
// if it doesn't compile you might need to add a
// conversion operator to MyList
std::vector<int> v = MyList()<<1<<2<<3<<4;
// This will slice to a vector correctly.
do_something_with_a_vec( MyList()<<1<<2<<3<<4 );
// This will pass a const ref - which will be OK too.
do_something_with_a_const_vec_ref( MyList()<<1<<2<<3<<4 );
//This will not compile as MyList::operator new is private
MyList * ptr = new MyList();
}
Другое допустимое использование, о котором я могу подумать, связано с отсутствием шаблонных typedefs в C ++. Вот как это можно использовать.
// Assume this is in code we cant control
template<typename T1, typename T2 >
class ComplicatedClass
{
...
};
// Now in our code we want TrivialClass = ComplicatedClass<int,int>
// Normal typedef is OK
typedef ComplicatedClass<int,int> TrivialClass;
// Next we want to be able to do SimpleClass<T> = ComplicatedClass<T,T>
// But this doesn't compile
template<typename T>
typedef CompilicatedClass<T,T> SimpleClass;
// So instead we can do this -
// so long as it is not used polymorphically if
// ComplicatedClass doesn't have a virtual destructor we are OK.
template<typename T>
class SimpleClass : public ComplicatedClass<T,T>
{
// Need to add the constructors we want here :(
// ...
private:
// Prevent heap allocation
void * operator new (size_t);
void * operator new[] (size_t);
void operator delete (void *);
void operator delete[] (void*);
}
Вот более конкретный пример этого. Вы хотите использовать std :: map с пользовательским распределителем для многих различных типов, но вы не хотите, чтобы unmaintainable
std::map<K,V, std::less<K>, MyAlloc<K,V> >
замусорил твой код.
template<typename K, typename V>
class CustomAllocMap : public std::map< K,V, std::less<K>, MyAlloc<K,V> >
{
...
private:
// Prevent heap allocation
void * operator new (size_t);
void * operator new[] (size_t);
void operator delete (void *);
void operator delete[] (void*);
};
MyCustomAllocMap<K,V> map;