Chiel
Chiel

Reputation: 6194

Mixing smart pointers to class objects with class objects

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

Answers (3)

ROX
ROX

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

Sergei
Sergei

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

user8394345
user8394345

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

Related Questions