-2

I would like to ask question regarding internal helper class in C++. What is the best way to structure this?

Let me clarify what do I mean by internal helper class by example.

// MyClass.h
class MyClass
{
    int myData;
    bool isSomething;
    ...
public:
    void DoSomething();
};

// MyClass.cpp
// This is what I mean by internal helper function. Helper function that's only visible int the implementation file (.cpp) but requires access to the private members of the class.
static void DoSomethingInternal( MyClass *myClass )
{
   // Access myClass private members
}

void MyClass::DoSomething()
{
    ...
    DoSomethingInternal(this);
    ...
}

I know that declaring friend function can be a solution. However, it makes the class declaration ugly. In addition, for every new helper function, I have to add a friend function.

Is there an idiom/design pattern for this? I have been searching in the Internet, but didn't find any.

Thank you in advance. Your answers are greatly appreciated.

stacknewbie
  • 13
  • 1
  • 3
  • Declaring a friend function is ugly because it's ugly to break encapsulation. If you want to not break it, then you shall either provide access to the required data (getters/setters) or change the function prototype and pass member data as parameters. – Nielk Jun 12 '15 at 16:01
  • 2
    You're probably going to be told that the "correct" thing to do is declare all of your 'helper' functions as private members or to use the "Pimpl" idiom, and you're probably going to think it is weird, and you'll be right, but those are the "accepted" paradigms. – kfsone Jun 12 '15 at 16:03
  • @Nielk Yes, I thought about providing access to the required data, but then it will add code bloat, especially if the setter/getter is only used for the internal helper function. Changing the function prototype to accept member data as parameters works but it also depends on how many parameters are needed. – stacknewbie Jun 12 '15 at 16:39
  • @kfsone - I like the idea of "Pimpl". However, generally it requires dynamic allocation, which is not that great – stacknewbie Jun 12 '15 at 16:40
  • @stacknewbie then what's wrong with private method ? More on that topic : https://isocpp.org/wiki/faq/strange-inheritance#private-virtuals – Nielk Jun 12 '15 at 16:48
  • @Nielk Private method will work, it just makes the header file more bloated with helper functions. Using private method or friend is probably the best bet, I was wondering if there's a better solution. – stacknewbie Jun 12 '15 at 17:03

5 Answers5

3

In my experience, a lot of dev teams have no problem with static local helper functions, it helps reduce header bloat, helps keep the formally exposed interface smaller, and so forth. It has the advantage of being lightweight, it has the disadvantage that it can lead to friend bloat/pollution if you are using lots of private members and no accessors.

But within the discussion community it is generally frowned upon in favor of the following.

  • Declaring helpers as private member functions.

This has the advantage of clearly associating fn _doThingsForFoo(Foo*) with Foo, and saving you from a lot of headaches exposing private members.

It has the downside of basically showing your underwear to everyone who needs to #include your header.

  • Using the Pimpl idiom.

You declare a second class, the "Private Implementation" (https://en.wikipedia.org/wiki/Opaque_pointer, Is the pImpl idiom really used in practice?) and you put all of the private stuff you don't want in the main header into that.

It has the advantage of allowing you to hide your stuff, it has the disadvantage of adding an extra pointer to feed, store and traverse (oh and free).

Community
  • 1
  • 1
kfsone
  • 21,566
  • 2
  • 35
  • 66
  • Declaring helpers as private member functions is the easiest way to do it. However, I agree that the downside is you are showing more stuff to everyone. EDIT: Another way I'm thinking is declaring static class (class that only contain static functions) in cpp and make that as a friend. – stacknewbie Jun 12 '15 at 16:48
  • I'm looking to make a formal proposal to the standards committee for `private` cu-scoped member functions; compilation-unit scoped functions that are private (so only accessible by member functions whose implementation occurs after their declaration). It helps reduce bloat while retaining the clear relationship to the class in the compilation unit. e.g. `class A { private: int i; public: void foo(); };` in the header, in the cpp: `private int A::bar() { return i * SomeLocalValue; }` followed by `void A::foo() { std::cout << bar() << "\n"; }` – kfsone Jun 12 '15 at 20:17
  • Yeah, If we have that mechanism that'd be great. – stacknewbie Jun 12 '15 at 21:11
1

There are couple of ways to accomplish that.

  1. Use a helper class/function in the .cpp file if the helper functions don't need access to the data directly. I would recommend this method ahead of the next method.

    In the .cpp file:

    // Create a namespace that is unique to the file
    namespace MyClassNS
    {
       namespace HelperAPI
       {
          void DoSomethingInternal(MyClass* obj) { ... }
       }
    }
    
    using namespace MyClassNS;
    void MyClass::DoSomething()
    {
        ...
        // 
        HelperAPI::DoSomethingInternal(this);
        ...
    }
    
  2. Use the pimple idiom. When using this idiom, you can add any number of helper functions in the private data class without touching the public interface of the class.

R Sahu
  • 196,807
  • 13
  • 136
  • 247
  • Yes, I would do (1) as much as I can. I probably will use anonymous namespace too. Pimpl works but then it requires dynamic allocation. – stacknewbie Jun 12 '15 at 16:42
0

The design pattern is simple: don't use helper classes. If a class should do something, let it do it itself.

StenSoft
  • 8,919
  • 20
  • 27
  • I agree with trying our best not to use helper classes. However, sometimes you need to breakdown (possibly for code reuse, readability, clarity) a function into smaller/helper functions. However, those smaller/helper functions are only useful in the context of that class. – stacknewbie Jun 12 '15 at 16:44
  • @stacknewbie In that case, I would suggest using another class either with inheritance (multiple inheritance is nothing bad in C++) or as a member (then it can be hidden in the interface via pimpl). Large methods and classes are usually caused by insufficient division of responsibilities. – StenSoft Jun 12 '15 at 18:07
  • You mean the helper class inherits from the main class? – stacknewbie Jun 12 '15 at 21:13
  • @stacknewbie Either that (pimpl) or the helper class can be parent of the main class and take care of some part of the responsibilities, therefore reducing what is in the main class's header – StenSoft Jun 12 '15 at 22:36
0

As per the upvoted answer given by StenSoft, you should implement the methods inside the class. However, if that is not an option for some reason, then use helpers. If even that is not an option, then use reflection. If even that is not an option, then use a command listener inside your class. If even that is not an option, then watch a tutorial.

Lajos Arpad
  • 45,912
  • 26
  • 82
  • 148
  • I'm trying to avoid adding private helper class in the header because it makes the header file more bloated/not so readable (just in my opinion). It seems like one solution is to declare the helper class as a friend in the header. – stacknewbie Jun 12 '15 at 16:52
0

You can read these following sites for this purpose PIMPL, Opaque pointer. With this you only need to have one member variable and you can put all private things into the private class.

your header:

class PrivateClass;

class Class
{
public:
    // ...

private:
    PrivateClass* m_Private;
};

your source:

class PrivateClass
{
// ...
};

Class::Class
: m_Private( new PrivateClass )
{
// ...
}

UPDATE: I forgot to tell mention to delete the private member in the desctructor.

Class::~Class
{
    delete m_Private;
// ...
}

// ...
p.i.g.
  • 2,559
  • 1
  • 19
  • 38