Самое простое, что нужно сделать - это объявить своих членов объектами. Таким образом, вам не нужно заботиться о копировании, уничтожении и назначении. Об этом все позаботятся автоматически.
Тем не менее, есть некоторые случаи, когда вам нужны указатели. В конце концов, управляемые языки (такие как C # или Java) фактически содержат объекты-члены с помощью указателей.
Наиболее очевидный случай, когда объект, который нужно сохранить, является полиморфным. В Qt, как вы указали, большинство объектов принадлежат огромной иерархии полиморфных классов, и их обязательное хранение указателями обязательно, так как вы заранее не знаете, какой размер будет иметь объект-член.
Пожалуйста, остерегайтесь некоторых распространенных ошибок в этом случае, особенно когда вы имеете дело с общими классами. Исключительная безопасность - большая проблема:
struct Foo
{
Foo()
{
bar_ = new Bar();
baz_ = new Baz(); // If this line throw, bar_ is never reclaimed
// See copy constructor for a workaround
}
Foo(Foo const& x)
{
bar_ = x.bar_.clone();
try { baz_ = x.baz_.clone(); }
catch (...) { delete bar_; throw; }
}
// Copy and swap idiom is perfect for this.
// It yields exception safe operator= if the copy constructor
// is exception safe.
void swap(Foo& x) throw()
{ std::swap(bar_, x.bar_); std::swap(baz_, x.baz_); }
Foo& operator=(Foo x) { x.swap(*this); return *this; }
private:
Bar* bar_;
Baz* baz_;
};
Как видите, довольно сложно иметь безопасные конструкторы при наличии указателей. Вы должны взглянуть на RAII и умные указатели (здесь и где-то еще в Интернете много ресурсов).