4

I have public member functions which are calling private member function. I want to limit the scope of the private member function within the file where definition of private member function is available. In C, I used static before the function name to limit its scope within the file, how do I achieve it in C++.

class Base
{
  public:
  void XYZ1(void);
  void XYZ2(void);
  private:
  void fun(void);
};

void Base::XYZ1(void)
{
  fun();
}

void Base::fun(void)
{
  // do something;
}

Now if the member function XYZ2 is defined in some other .cpp file , it should not be allowed to call fun() from it. Basically restrict the fun() function to file scope. In a1.cpp

void Base::XYZ2(void)
{
  fun();// this should result in some error saying fun() is not defined in its scope.
}
Manoj Patil
  • 155
  • 8
Dipanjan
  • 181
  • 3
  • 12
  • I don't think such a thing is possible, at least not in a portable way. – user253751 Feb 04 '16 at 06:46
  • C++ also lets you use `static` for internal linkage, but it has a different meaning for member functions. It's not a question of C vs. C++. – chris Feb 04 '16 at 06:46
  • 1
    Does `fun()` need to be a member function, or can it be a non-member? – juanchopanza Feb 04 '16 at 06:48
  • 4
    The only solution is to not make them member functions, but "normal" non-member functions. Then you can make them either `static` as in C, or put them in an anonymous namespace. This will of course lead to problem if the functions needs to access other private members (functions or variables), in which case you should read about [the pimpl idiom](http://c2.com/cgi/wiki?PimplIdiom). – Some programmer dude Feb 04 '16 at 06:48
  • (A non-portable way would be #ifdef'ing out the declaration in the header file, and then defining the macro only in the source files you want to see it, by the way. Likely to work on many compilers, and potentially not working on some) – user253751 Feb 04 '16 at 06:52
  • 1
    Pedantically speaking, `static` [limits linkage, not scope.](http://publications.gbdirect.co.uk/c_book/chapter4/linkage.html) – Vorac Feb 04 '16 at 06:56

5 Answers5

7

I want to limit the scope of the private member function within the file where definition of private member function is available.

A private member function cannot be used by another class or function unless they are granted friend-ship by the class. In that sense, the scope in which the function can be called is already limited.

Having said that, any member function of the class or any class or function that has been granted friend-ship by the class will be able to call the private member function.

The only way to prevent that function from being called outside the file in which it is defined is to make it a non-member static function in the .cpp file. or put it in an anonymous namespace in the .cpp file.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

Now if the member function XYZ2 is defined in some other .cpp file , it should not be allowed to call fun() from it. Basically restrict the fun() function to file scope. In a1.cpp

You can put the function in an anonymous namespace (in the cpp file where used). The linkage will become internal, and the name won't be available for access from any other file. One can get the same effect when making the function static (in the cpp file).

If you need to access internal/private members, you could use a nested class who's implementation is defined in the associated cpp file:

//h
class Nesting
{
    //...
  private:
    struct MyPrivateFunctions;
};

//cpp

struct Nesting::MyPrivateFunctions
{
  static void f1(Nesting& this);
  static void f2(Nesting& this);
  //etc...
};

I've passed Nesting as parameter that MyPrivateFunctions may access its private members (since it is nested, this is permitted).

Note that this is very similar to the Impl trick mentioned elsewhere, but it also allows independent member function definitions in other units, and it does not need instantiation.

Werner Erasmus
  • 3,988
  • 17
  • 31
1

Or you can use the good old Impl- trick if you do not want to show the "hidden" functions of a class to the outside. Private functions are still listed in the header file, after all.

// Foo.h
class FooImpl; // forward declearation
class Foo
{
    FooImpl *m_pImpl;
    public:
    Foo(); // Default constructor (and any other) create instance of FooImpl.
    ~Foo();
};

// Foo.cpp
class FooImpl
{
   // members of hidden types, secrets, methods, ... anything you do not want to show to users of class Foo.
};
Foo::Foo() : m_pImpl(new FooImpl()) {}
Foo::~Foo() 
{
     delete m_pImpl; m_pImpl = nullptr;
}

As can be seen, with the impl trick you cannot only hide functions, but also data members of a class and type dependencies which would be incurred if the members were part of Foo class.

BitTickler
  • 10,905
  • 5
  • 32
  • 53
1

Most people are suggesting you to use anonymous namespace in C++. But, this would only be feasible if you wanted to do something like, declaring a global variable/function which is supposed to be used strictly inside the file under which it is defined.

We cannot use namespace within the class as per C++ standards, for which you may want to take a look at this discussion: Why can't we declare a namespace within a class?

I used static before the function name to limit its scope within the file.

This worked for you but the understanding here is wrong as static was never intended to be used as scope specifier, its a storage specifier and its lifetime is throughout the program life. You can still access the static variable from other files in several ways, however the compiler here does not provide an externally visible linker symbol and thus cannot be accessed by other translation units / files.

As per the public member functions are concerned they should be allowed to use this private function from whichever file it is defined in. So that the relation between the class member functions are not destroyed. I suppose you would now stop treating static as scope specifier :)

Manoj Patil
  • 155
  • 8
0

A way to solve this problem is by using a so called 'facade'. Basically, you have two classes: The first class has the private method which you want to hide, where as the second class implements a wrapper which just provides the methods you want to be accessible. The second class wraps an instance of the first. That's how the whole trick works.

https://en.wikipedia.org/wiki/Facade_pattern