For a long time now I’ve perceived pointers, new and delete somewhat unnecessary in C++ unless dealing with long-lived objects, with references being a cleaner alternative that fits better in the RAII model. However, I am still unable to ascertain how to avoid pointers when using dynamic polymorphism in C++.
Supose we have these clasess:
class A
{
public:
virtual void a() const = 0;
};
class B : public A
{
virtual void a() const
{
std::cout << "B";
}
};
class C : public A
{
virtual void a() const
{
std::cout << "C";
}
};
void invoke(const A& obj)
{
obj.a();
}
int main()
{
B b;
invoke(b); // Prints B
}
Object can be passed to invoke as a reference and there are no pointers involved (well, at least from the programmer’s perspective). However, the above example is essentially static polymorphism.
If I wanted to make the type of b dependent on something else, I would have to use pointers:
int main()
{
A* a;
if (something)
a = new B;
else
a = new C;
invoke(*a); // Prints B
delete a;
}
This looks ugly as hell to me. Sure, I could use smart pointers:
int main()
{
std::unique_ptr<A> a;
if (something)
a.reset(new B);
else
a.reset(new C);
invoke(*a); // Prints B
}
But smart pointers are just wrappers for pointers.
I would like to know if there is a way to avoid this and utilize polymorphic classes without the use of pointers.
You can’t avoid pointers for this. If you don’t like them C++ isn’t going to be the language for you, because if you want to do anything polymorphic you’re going to have to use pointers to get past the most trivial uses. Constructing objects on the heap, i.e. using
newis how you avoid the scoped lifetime of stack-constructed objects, which you have to do if you want to make things inside conditional branches and then assign them to variables in a parent scope – if you don’t need to do that you also don’t actually need polymorphism because your types are all determinable at compile time. There’s no way around this.Use smart pointers of course, they can really help avoid issues with pointer lifecycles, but there’ll be pointers in there somewhere no matter what really cool abstractions you end up using.