Reputation: 6194
I have a code where by design some classes use a factory function to generate the actual class, and others do not. Many classes have functions with the same names implemented and those functions are called sequentially (see below). This design results in mixing smart pointers to objects and objects itself. Is the code below bad design and should I use smart pointers everywhere?
#include <iostream>
#include <memory>
class A
{
public:
void print_name() { std::cout << "A\n"; }
};
class B
{
public:
virtual void print_name() = 0;
static std::unique_ptr<B> factory(const int n);
};
class B1 : public B
{
public:
void print_name() { std::cout << "B1\n"; }
};
class B2 : public B
{
public:
void print_name() { std::cout << "B2\n"; }
};
std::unique_ptr<B> B::factory(const int n)
{
if (n == 1)
return std::make_unique<B1>();
else if (n == 2)
return std::make_unique<B2>();
else
throw std::runtime_error("Illegal option");
}
int main()
{
A a;
std::unique_ptr<B> b1 = B::factory(1);
std::unique_ptr<B> b2 = B::factory(2);
// The block below disturbs me because of mixed . and ->
a.print_name();
b1->print_name();
b2->print_name();
return 0;
}
EDIT
I have added smart pointers to the example following the comments below.
Upvotes: 1
Views: 219
Reputation: 1266
Other than the mix, why does the code disturb you? What do you think could actually go badly because of it? Do you think the difference really hurts readability?
Yes the lines that call print look different, and that difference tells you that the objects are being managed in a different way.
There's no obvious benefit to them being made the same, if a developer can't understand both . and -> then you have much bigger problems.
I've worked on a codebase where nearly everything was handled by shared pointers for consistency, even though some things shouldn't be pointers and most aren't really shared. Needless inconsistency should be avoided but it really isn't helpful to be consistent in cases where that hides legitimate difference.
One benefit of your code over all pointers is that since a is not a pointer you can sure that a is not null.
Upvotes: 0
Reputation: 550
This looks like a reasonable design to me. In the client code you will work through the base class interface.
class Base {};
class A: public Base {};
class B: public Base {};
class B1: public B {};
class B2: public B {};
class Factory {
std::unique_ptr<Base> create(const int n) {
// Instantiate a concrete class based on n
return std::unique_ptr<Base>(new A());
}
}
Upvotes: 1
Reputation:
Generally, you should avoid using pointers, if not needed. Topics like Return Value Optimization make them optional in most cases. Also, don't use C-Style-Pointers. C++11 introduced the memory-header, which includes many useful smart pointers.
And yeah, I feel like using those pointers in such a program is a bad design decision.
Upvotes: 0