Élodie Petit
Élodie Petit

Reputation: 5914

Calling functions of static members

This is my class definition:

#ifndef CloudFunctions_hpp
#define CloudFunctions_hpp

#include "WebRequest.hpp"
#include "external/json/document.h"
#include <stdio.h>

typedef std::function<void(const rapidjson::Document&)> CloudCallback;

class CloudFunctions
{
private:
public:
    static WebRequest request;
    static void GetData(const CloudCallback &callback);
};

#endif /* CloudFunctions_hpp */

Basically this class downloads data from a rest api and calls the function in the callback parameter.

This is the GetData function:

void CloudFunctions::GetData(const CloudCallback &callback)
{
    CloudFunctions::request.get("decks", [&](const std::string &result){
        CCLOG("Loaded");
    });
}

Unfortunately, this doesn't compile:

Undefined symbols for architecture x86_64:
  "CloudFunctions::request", referenced from:
      CloudFunctions::GetData(std::__1::function<void (rapidjson::GenericDocument<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>, rapidjson::CrtAllocator> const&)> const&) in CloudFunctions.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

If I turn request member and GetData function into non-static, then the code compiles.

What's going on here?

Upvotes: 1

Views: 63

Answers (3)

Lukas
Lukas

Reputation: 1305

You need to define your static member variable request. All you did is to provide a declaration for it. see also Undefined reference to static variable c++

For example:

class A
{
public:
  static int var;
};

In your cpp you can initialize it then:

int A::var = 0;

Then you can use it like this:

int main()
{
  A::var = 5;
}

Upvotes: 3

FinnTheHuman
FinnTheHuman

Reputation: 1155

Because request is static data member, you have to initialize it on global scope, outside the class declaration. static data members don't get initialized by any constructor (because they don't belong to any instance), so in the class declaration you're just declaring the static data member, not initializing it (or instantiating it or any other term you prefer). you need a static context to initialize static data, so that's why you do it on global scope. Even if the member is private, you can do that.

so, outside any class, you just type WebRequest CloudFunctions::request;

Upvotes: 1

LLFF
LLFF

Reputation: 31

Your implementation cc file should include the following line:

WebRequest CloudFunctions::request; // include constructor arguments here

Take care not to run into the static initialization order fiasco. If other implementation files have static initialization that depends on CloudFunctions::request, they could possibly end up using it before it is initialized/constructed.

Consider using a singleton instead.

Upvotes: 1

Related Questions