Your static member function, or friend function, which is the factory should have no problem with calling protected constructors and returning a smart pointer. Generally plan to return a std::unique_ptr<BaseClass>
which can be converted into a std::shared_ptr
if the caller wants that instead.
Make the virtual destructor public.
Update: Don't bother making the factory a friend. You only need to prevent the construction of the base and intermediate classes. Make them effectively hidden and private by hiding the implementation classes in their own source file. Or an anonymous namespace I suppose.
Here have some code of how I would do it:
#include <iostream>#include <memory>#include <string>// ITest is the only class any other code file should ever see.class ITest {protected: ITest() = default;public: virtual ~ITest() = 0; virtual int getX() const = 0; virtual int getY() const = 0;};// Destructors must always have an implementation even if they are pure virtual.ITest::~ITest() {}std::ostream &operator<<(std::ostream &os, const ITest &x) { return os << '['<< x.getX() << ','<< x.getY() << ']';}// Declaration of constructTest factory function.// Its definition should be hidden in a cpp file.std::unique_ptr<ITest> constructTest(int x);// The main function does not need to know anything except the ITest interface// class and the constructTest function declaration.int main(int argc, char *argv[]) { int val = 0; if (argc > 1) val = std::stoi(argv[1]); auto p = constructTest(val); std::cout << *p << std::endl;}// These classes should be defined in a private header file or in a cpp file.// Should not be visible to any other code. It has no business knowing.// Hiding all of this implementation is sort of the point of abstract interface// classes and factory function declarations.class TestBase : public ITest {private: int x = 0; int y = 0;protected: TestBase(int x = 0, int y = 0) : x(x), y(y){};public: int getX() const override { return x; } int getY() const override { return y; }};class TestA final : public TestBase {public: TestA() = default;};class TestB final : public TestBase {public: TestB(int x, int y) : TestBase(x, y) {} int getX() const override { return -TestBase::getX(); }};std::unique_ptr<ITest> constructTest(int x) { // make_unique is c++14. // For C++11 use std::unique_ptr<ITest>(new TestB(x, x) if (x) { return std::make_unique<TestB>(x, x); // return std::unique_ptr<ITest>(new TestB(x, x)); } return std::make_unique<TestA>();}