Say I have a class as follows in a header file:
class A {
public:
void foo();
}
The function foo needs to call another "helper" function named bar. Bar isn't needed anywhere else other than inside foo. Should it be defined statically outside the scope of A:
(source file)
static void bar() { ... }
void A::foo() {
bar(); ...
}
or within the class?
(header)
class A {
public:
void foo();
private:
void bar();
}
(souce)
void A::bar() { ... }
void A::foo() {
bar(); ...
}
Bar isn't needed anywhere else other than inside foo.
If so then bar should be a private member function of class A - there is no need to define bar in global namespace.
static void bar() { ... } // not needed
instead use:
void A::bar() { ... } // <- bar should be private member function
Generally, you should only allow access to the internals of a class when necessary. Placing the function outside the class and restricting its scope--either as a static function or within an anonymous namespace, would be best. That way, you're not polluting the global namespace and you're not allowing unnecessary access to class internals.
For example, you can, in the class's cpp file, have:
namespace {
void bar() {.....}
}
and that helper function is then available for your class methods in the same cpp file.
Static functions in the cpp file would also have file scope only, but I find the static keyword to be confusing when used that way.
Related
I wonder what is the better practice to call a static function(and variables) inside a class or struct between A and B.
A: ClassName::functionName();
B: functionName();
Here's my simple example code:
In header file,
typedef struct _mystruct
{
static void myfunction();
} t_mystruct;
And in CPP file,
void t_mystruct::myfunction()
{
//do something
}
Now, in the same CPP file, what is the better practice to call this static function between A and B?
A: t_mystruct::myfunction();
B: myfunction();
Calling straight myfunction(); is only feasible if you are inside t_mystruct's implementation. In which case you can do according to your preferred coding style:
// .h
struct t_mystruct // You can declare it directly that way
{
static void myfunction();
void myOtherFunction();
};
// .cpp
void t_mystruct::myOtherFunction()
{
myfunction(); // That's fine!
t_mystruct::myfunction(); // That's fine too!
}
Otherwise, you have to explicitely use its fully qualified name:
void anywhereElse()
{
t_mystruct::myfunction(); // Mandatory
myfunction(); // Does not compile
}
This is true for your whole codebase, not only for the considered .cpp file.
Using C and plain functions in C++, I can prevent the functions' symbols to be exported by using static keyword:
static int foo(int a, int b) { /* ... */ }
But in a class, defining a function as static has a completely different meaning. Is there a way to ensure the compiler that my whole class will be used only within module, and there is no need to export any of its methods' symbols?
Use an anonymous namespace.
namespace
{
class C
{
C() {}
void f() {}
};
void f();
}
class ExportedClass
{
ExportedClass() {}
void f() {}
};
void exportedFunction() {}
As you can see, you should do this for normal functions, too. The usage of static for this is discouraged.
You can use the anonymous namespace. For example,
// file foo.cc
namespace {
int symbol1 = 0;
struct auxiliary { /* ... */ } symbol2;
}
void foo(int x)
{
// uses symbol1 and symbol2
}
when symbol1 and symbol2 are not 'visible'.
Depending on what you want and why you are doing it you could move the class into the .cpp file. This works for example if you are implementing a library. Have a look at the discussion at Putting class declaration in .cpp file
To be more specific your class should go in it's own separate translation unit away from main and away from classes outside of your module.
This code does not compile:
class A;
void foo(A&) {
}
class A {
void foo() {
foo(*this); ///This does not compile
}
};
Errors:
error: no matching function for call to 'A::foo(A&)'
foo(*this);
^
note: candidate is:
note: void A::foo()
This can be solved by calling ::foo(*this);
However, let's consider the case we are in a namespace:
namespace bar {
class A;
void foo(A&) {
}
class A {
void foo() {
foo(*this); ///This does not compile
}
};
}
Is there any other way than calling explicitly bar::foo(*this);? I mean, is there any way to look up names in the next surrounding declarative region, i.e. the containing bar namespace?
The use case is similar to what seen here.
I mean, is there any way to look up names in the next surrounding declarative region,
i.e. the containing bar namespace?
No.
You can sort of do it the other way around:
void foo() {
using bar::foo;
foo(*this); /// OK now
}
Not within the method itself. However, you can do this in the .cpp file:
namespace bar {
namespace {
auto outerFoo = foo;
}
void A::foo() {
outerFoo(*this);
}
}
Note that the name outerFoo is a hidden implementation detail which cannot cause name collisions (since it's in an anonymous namespace).
How could I make a function only seen by the function that calls it?
define the function I want to hide as private function is not enough, as it could still be seen by other public functions in the class.
Now I use lambda expression to define anonymous function inside function. Is there any better solution?
Aside from using a lambda (which you've rejected), you could implement your function in its own compilation unit, and code the supporting function in an anonymous namespace within that compilation unit.
But that supporting function would be outside the class, so you'd have to pass it all the parameters it needed. That could become unwieldly though no worse than a long lambda capture list.
You can use a function object. For example(you can compile this, even in C++03):
#include <iostream> // only for output
class foo{
int bar(){return 0;} // Only foo can see this
public:
int operator()(){
return bar();
}
};
class baz{
public:
foo do_foo;
};
int main(){
baz a;
std::cout << a.do_foo() << std::endl;
}
the method bar is only visible by a foo.
P.S.: If you need foo to access members of baz, make it a friend.
A simmilar approach to cassiorenan would be to use static class functions and friends.
Something like this:
void Boss();
class Worker {
static void Test(){ return;}
friend void Boss();
};
void Boss(){
Worker::Test();
}
Though why would you want to do this, I don't know.
It is possible to define function inside a function without lambdas. Just define a struct that contains required function. This approach is not much better than using lambda, but at least this is straightforward and works with older compilers too.
int func() {
struct {
int hiddenFunc() {
return 1;
}
} h;
int a = h.hiddenFunc() + h.hiddenFunc();
return a;
}
As a slight variation from cassiorenan's solution, you could use a class containing one public static function (the visible function) and one static private function that could only be called from there. To avoid creation of objects of that class, it is enough to put a private constructor.
EDIT:
Per cassiorenan's comment, I can see that OP really needs methods and not functions. In that case, I would still use a dedicated class in a anonymous namespace to ensure it is not visible from elsewhere (even if my example is single file ...) friend to the class really used. So in below example, bar is the business class that would have a method with an externally hidden implementation (here relay_method), and foo is dedicated to the hidden method called with a pointer to the real object. In real world, the whole anonymous namespace and the implementation of the hidden method should be in the implementation file bar.cpp.
That way, the real implementation function priv_func can only be called from a bar object through bar::relay_method() and foo::bar_func(bar &).
#include <iostream>
class bar;
namespace {
class foo {
private:
static int priv_func(int i) {
return i * i;
}
foo() {}
public:
// only useful if true functions were needed
/* static int pub_func(int i, int j) {
return priv_func(i) + priv_func(j);
}*/
static void bar_func(bar& b);
};
}
class bar {
int x;
int x2;
public:
bar(int i): x(i) {}
void relay_method() {
foo::bar_func(*this);
}
friend class foo;
int getX2() const {
return x2;
}
};
void foo::bar_func(bar& b) {
b.x2 = foo::priv_func(b.x);
}
using namespace std;
int main() {
/* int i = foo::pub_func(3,4);
cout << i << endl;
// foo::priv_func(2); error access to private member of class foo
// foo f; */
bar b(2);
b.relay_method();
cout << b.getX2() << endl;
return 0;
}
I want to only have 2 extern C functions, which are how to interact with the API. Then inside the static .lib I want to have my class that does all the work. But it shouldnt be visible to the outside.
I can do it with just pure C functions by declaring them static inside a compilation unit, but how do I do it with a class ?
If I understand your question well:
you want to create a static library presenting only two functions to the outside world
but the internals of this library should be based on a class you want to hide from outside world.
you know how to do hiding internals in classic c (i.e. using auxiliary static functions and static variables) but you don't see how to do with classes
If this is the case, the trick is simply to use an unamed namespace:
In your library source you would have something like this:
namespace { // anonymous
class U { // class visible only to the library
public:
int y;
U() :y(0) { cout << "U\n"; }
void mrun() { y++; }
};
}
void f() {
U x;
...
}
You may then use your library from outsilde world:
extern void f(); // declare the function (in a header)
f(); // invoke the function
Even if the auxiliary class would be declared in the outside world:
class U { public: int y; U(); void mrun(); };
It would not be able to used and linking errors would be generated if it would be tempted to use U. This is because unnamed namespaces are unique to each compilation unit.
If you use the same kind of solution but without the anonymous namespace, the auxiliary class would be visible and the link would succeed.
Perhaps you could mirror the class's API using C functions a bit like this:
class Cpp
{
int i = 0;
public:
int get_i() { return i; }
void set_i(int i) { this->i = i; }
};
// C code has a void* as a handle to access
// the correct instance of CPP
extern "C" void* new_Cpp()
{
return new Cpp;
}
extern "C" void delete_Cpp(void* cpp)
{
delete reinterpret_cast<Cpp*>(cpp);
}
extern "C" int Cpp_get_i(void* cpp)
{
return reinterpret_cast<Cpp*>(cpp)->get_i();
}
extern "C" void Cpp_set_i(void* cpp, int i)
{
return reinterpret_cast<Cpp*>(cpp)->set_i(i);
}