Private member functions and structures and helpers local to the implementation file

Consider a class with a set of methods

class myClass {
  private:
    int someFunc(const SomeClass&);
  public:
    funcA();
    funcB();
    funcC();
}

      

Inside the implementation file I have a local structure definition and some helper functions using this in an anonymous namespace

namespace {
  struct Foo { ... };
  int helperFunc(const Foo&){
    SomeClass c;
    // do stuff with Foo and SomeClass to calculate someInteger
    return someInteger;
  }
  Foo makeFoo(){
     Foo foo;
     // configure foo
     return foo;
  }
}

myClass::funcA(){
  Foo foo = makeFoo();
  return helperFunc(foo);
}
myClass::funcB(){
  Foo foo = makeFoo();
  return helperFunc(foo);
}
myClass::funcC(){
  Foo foo = makeFoo();
  return helperFunc(foo)
}

      

Now I found that I need to change helperFunc

, in order to use someFunc(c)

, the private method myClass

.

Ideally I would like

  • store Foo

    local definition in anonymous namespace
  • keep someFunc

    closed
  • save helperFunc

    as a function as it has been used multiple times in the class implementation
  • keep makeFoo

    separate from helperFunc

    , because it is used separately in some cases

As a last resort it can be converted helperFunc

to a precompiler macro, but I find this is not very elegant and still hopes there is some trick that I do not know about achieving my goals.

I really appreciate any suggestions.

+3


source to share


3 answers


There is more than one way to do this. Personally, I would go with:

namespace detail
{
    int myClassSomeFuncAccessor(const SomeClass&);
}

class myClass {
  private:
    int someFunc(const SomeClass&);
  public:
    int funcA();
    int funcB();
    int funcC();

  private:
    friend int detail::myClassSomeFuncAccessor(const SomeClass&);
};

      

It has pros and cons.

Pros:



  • Overrides a class and its accessor from implementation classes

  • detail

    Namespace accessory means it is not part of the "official public" interface

Minuses:

  • The decoupling is really unbound: anyone can access internals via the detail

    accesspace
+3


source


You can pass an object std::function

to helperFunc

. This object can be created from your private method with std::bind

:



namespace {
  ...
  int helperFunc(const Foo&, std::function<int(const SomeClass&)> func){
    SomeClass c;
    ...
    // Invoke passed-in function
    int funcResult = func(c);
    ...
    return someInteger;
  }
  ...
}

myClass::funcA(){
  Foo foo = makeFoo();
  return helperFunc(foo, std::bind(&myClass::someFunc, this, std::placeholders::_1));
}

      

+4


source


I think this is now the perfect use case for the "friend" keyword in C ++. Just make your inner friend of the encapsulator class. This is the cleanest and most language-friendly solution. In an article about Alex Allain's topic, he explains perfectly how a friend in C ++ is not forbidden by saying

Some people think that the idea of ​​having friend classes violates the principle of encapsulation because it means that one class can get trapped inside another. One way to think about this, however, is that the friend is simply part of the general interface of the class that shows the world. Just as an elevator master has access to a different interface than an elevator rider, certain classes or functions require extended access to the internals of a different class. Moreover, using a friend allows the class to present a more restrictive interface to the outside world, hiding more detail than anyone other than the class's friends might need.

+3


source







All Articles