4

in hello.cpp file, I have this static function.

static void hello()
{
    std::cout << "hello" << std::endl;
}

And I would like to call this function from other static function in world.h file like the following.

static void world()
{
    hello();
    std::cout << "world" << std::endl;
}

In this case, what is the most recommended way to expose hello() to other files?

Zack Lee
  • 2,784
  • 6
  • 35
  • 77

2 Answers2

6

Used that way, the keyword static makes your function's linkage "internal". This means hello() is only visible from hello.cpp, even if you declare it to other compilation units.

For example, the code below produces a linkage error (unresolved external reference):

hello.cpp:

#include <iostream>

static void hello()
{
    std::cout << "hello" << std::endl;
}

hello.h:

#pragma once

void hello(); // OK, it's declared

main.cpp:

#include "hello.h"

void main()
{
    hello(); // But ouch, it's not resolved! The linker can't access to the code you wrote in hello.cpp due to the fact hello() is static!
}

So you can't expose your function that way, by definition.

Now, if you declare your function static and implement it straight in its header file, after having removed hello()'s code from hello.cpp:

hello.h:

#pragma once

static void hello() 
{
    std::cout << "hello" << std::endl;
}

You will end up with as many functions hello() as you have compilations units that include this file. Give a try by including hello.h in several .cpp files and take a pointer to this hello function from each of these files. You will see that their addresses differ:

main.cpp:

#include <iostream>
#include "otherFile.h"

void main()
{
    void * pf = hello; // Gives 0x01181810 during the test I'm currently doing while writing

    tryWithAnotherCppFile();
}

otherFile.h:

#pragma once

void tryWithAnotherCppFile();

otherFile.cpp:

#include "otherFile.h"
#include "hello.h"

void tryWithAnotherCppFile()
{
    void * pf = hello; // Here it gives 0x01181d40, which is different!
}

Now, change hello.h the following way, by declaring hello() as inline instead of static:

hello.h:

#pragma once

inline void hello() 
{
    std::cout << "hello" << std::endl;
}

And redo the same test as above: you will see that hello()'s address is now the same regardless the cpp file that includes hello.h (0x003c13de, on my end, right now). Your function is no longer static, it has an external linkage and is unique and shared among all compilation units.

Further details are available in this tutorial. One relevant piece, but I suggest reading the whole thing:

When a symbol has internal linkage, it will only be visible within the current translation unit. Do not confuse the term visible here with access rights like private. Visibility here means that the linker will only be able to use this symbol when processing the translation unit in which the symbol was declared, and not later (as with symbols with external linkage). In practice, this means that when you declare a symbol to have internal linkage in a header file, each translation unit you include this file in will get its own unique copy of that symbol.

Shlublu
  • 10,917
  • 4
  • 51
  • 70
  • Which one do you think is a better solution 1) Putting the function only in the header as `inline`. 2) Creating the class and with static function inside it and call it with `classname::hello();` from other file. – Zack Lee Jul 04 '18 at 09:48
  • 1
    @ZackLee This really depends on what you need to do. Why would your function need to be static? Why would it need to be inline? Can't it just be declared in its .h and implemented in its .cpp to be shared with all those that include hello.h as usual? In your original question, there's nothing related to object oriented programming, but depending on what you are actually developping, there could be a point in defining this function as a static class member (so a function that is applies to a class rather than its instances), but we don't have enough elements here to determine that. – Shlublu Jul 04 '18 at 09:57
  • If I not define functions as static in the header, it says conflicting types for the function. I think it's because I have functions that use same name but different arguments. – Zack Lee Jul 04 '18 at 11:27
  • 1
    @ZackLee Overloads Probably. If they only differ by their return type overloaded functions are seen as conflicting, as the compiler can't determine which one to take. I think you should revisit the design of your app. There's no shame to redesign your software from scratch after having encountered issues should this be feasible in practice. I suggest reading that, too: https://www.tutorialspoint.com/software_architecture_design/object_oriented_paradigm.htm – Shlublu Jul 04 '18 at 11:54
1

If its in Public scope of class, we can use scope resolution operator( :: ) to access the static functions with out initalizing an object.

class Hello
{
public:
    static void Hello1()
    {
        printf("Hello\n");
    }

};

Then from the Other Class ie World.cpp (Remember to include the hello.h File).

class World
{
public:
    World(){
        Hello::Hello1(); 
        std::cout << "World" << std::endl;
    }
};
Kiran Thilak
  • 443
  • 5
  • 15