Since you do not want Q to know about B and C, you have to store the A indirectly by a pointer, since you cannot know how much storage B, C or a yet unknown derived class D will need. The classic solution for a single object that is allocated dynamically and owned by Q is a std::unique_ptr.
Since std::unique_ptr by default uses delete to delete the object, you also need a virtual destructor in A.
#include"A.hpp"
#include<memory>
class Q {
std::unique_ptr<A> a;
public:
Q(std::unique_ptr<A> ai) : a{std::move(ai)} {}
};
If you do not want exclusive ownership of Q over the A, or do not want to provide a virtual destructor, you can also use a std::shared_ptr. Shared pointers remember the stored class dynamically and thus destroy the object correctly if they are created appropriately, notably with std::make_shared<MostDerivedClass>. Also they use reference counting and will delete the object only after all references to the object are gone.
The downside is a bit of extra memory needed and some runtime cost, compared to std::unique_ptr which usually has no overhead compared to a plain pointer.