Skip to content

KVS_CPP: hide implementation of public functions #119

@vbogdanb

Description

@vbogdanb

It is need to make the constructor public for the KVS to solve some issues with the mocking of the KVS class.
But with this would expose the constructor in the public api and would make it possible to directly construct a KVS object without the KVSBuilder .

To hide the constructor the following approach can be used:

IFoo.hpp (public)

#pragma once
#include <memory>

class IFoo {
public:
    virtual void doSomething() = 0;
    virtual ~IFoo() = default;
};

FooBuilder.hpp (public)

#pragma once
#include <memory>
#include "IFoo.hpp"

class FooBuilder {
public:
    FooBuilder& setOption(int value) {
        option = value;
        return *this;
    }

    std::unique_ptr<IFoo> build();  // returns only the interface

private:
    int option = 0;
};

Foo.hpp (private, internal to library)

#pragma once
#include "IFoo.hpp"
#include <memory>

class FooImpl;  // hidden implementation

class Foo : public IFoo {
public:
    void doSomething() override;
    ~Foo();

private:
    explicit Foo(int option);
    std::unique_ptr<FooImpl> impl;

    friend class FooBuilder;  // builder can call Foo's ctor
};

Foo.cpp (private, internal to library)

#include "Foo.hpp"
#include "FooBuilder.hpp"
#include <iostream>

// ----- Hidden implementation -----
class FooImpl {
public:
    explicit FooImpl(int option) : option(option) {}

    void doSomethingImpl() {
        std::cout << "FooImpl doing something with option = "
                  << option << std::endl;
    }

private:
    int option;
};

// ----- Foo -----
Foo::Foo(int option) : impl(std::make_unique<FooImpl>(option)) {}
Foo::~Foo() = default;

void Foo::doSomething() {
    impl->doSomethingImpl();
}

// ----- Builder -----
std::unique_ptr<IFoo> FooBuilder::build() {
    return std::unique_ptr<IFoo>(new Foo(option));
}

main.cpp (user code)

#include "FooBuilder.hpp"

int main() {
    auto foo = FooBuilder()
                   .setOption(42)
                   .build();

    foo->doSomething();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions