everyone! there is a code snippet like the below: testcase.cpp
#include <string>
#include <iostream>
using namespace std;
class Test {
public:
static int b ;
static void test()
{
b = 3;
cout << b<<endl;
}
};
int main()
{
Test::test();
return 0;
}
when I click "build" button,the output message is
error LNK2001: unresolved external symbol "public: static int Test::b" (?b@Test@@2HA) 1>B:\\PROGRAMPROJECT\\visual 2015 pro\\testcase\\testcase\\x64\\Debug\\testcase.exe : fatal error LNK1120: 1 unresolved externals
but,when i change the code location like this:
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
class Test {
public:
//static int b;
static void test()
{
static int b;//only change this line
b = 3;
cout << b << endl;
}
};
int main()
{
Test::test();
return 0;
}
It does work! I don't know why?Anybody can help me? My IDE is vs pro 2015 + windows10.
The other anwers focus on solving the problem, instead of answering the "why" part.
When you define a function within class body, it is automatically considered to be inline
and any number of translation units (think about C++ sources) may define them. That's the way you would normally define functions within header file - a function that's body will be include
d in multiple sources.
When you only declare a function within class body, but define it outside, it is not automatically marked as inline
, which means that each translation unit that contains this definition will generate its own strong symbol. In this case, you usually decouple the declaration in a header file, from implementation in an associated source file, otherwise you'd get multiple symbol errors. (ie if you have non-inline definitions in headers, each source that include them generates those symbols and linker gets confused because it sees multiple versions of the same non-inline function coming from different sources)
Now, when you define a static member variable, unless it's inline, it also must be also associated with a translation unit. It's similar to declaring an extern
global variable, that also has to be defined somewhere. In your case, you should simply add:
int Test::b;
It's more important when you decouple definition from declaration. Say, you have two files:
Test.hpp
class Test {
public:
static int b ;
static void test();
};
Test.cpp
#include "Test.hpp"
int Test::b;
void Test::test()
{
b = 3;
cout << b<<endl;
}
The symbols (in this case, the global variable Test::b
and the function Test::test
) are associated with the file Test.cpp and are generated exactly once. You may include Test.hpp in any number of source files and no additional symbols will be generated.
For referece, see https://en.cppreference.com/w/cpp/language/static
You've declared Test::b
but you haven't defined it. Add this line to your code (outside of the Test class)
int Test::b;
you can give an initial value as well if you wish
int Test::b = 123;
How to solve it
Using C++17
you can inline the static variable which removes the need to define it outside the class.
static inline int i = 0; // I would also initialize it to zero, just to be sure
If you cannot use C++17
you will have to define
int Test::b = 0; // Again I would also initialize it to zero, just to be sure
outside of class Test
To the why
When you wrote
static void test()
{
static int b; // <-- definition is here
b = 3;
cout << b << endl;
}
you defined the function directly in the class (which means it is automatically marked inline). You then also have the definition of your static variable right there. If it is outside of the function scope, it is only a declaration (except if explicitly marked as inline - as shown above).
In contrast, in the other case it is outside of the function definition and hence your are missing the definition of the static variable.
class Test {
public:
static int b ; // <-- only declaration - definition is missing
static void test()
{
b = 3;
cout << b<<endl;
}
};
Fix spelled out for C++17
class Test {
public:
static inline int b = 0; // <-- now it is defined (and for safety initialized)
static void test()
{
b = 3;
cout << b<<endl;
}
};
Fix spelled out prior to C++17
#include <string>
#include <iostream>
using namespace std;
class Test {
public:
static int b; // declaration
static void test()
{
b = 3;
cout << b << endl;
}
};
int Test::b = 0; // definition
int main()
{
Test::test();
return 0;
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.