为什么我不能像这样在静态成员函数中调用静态成员变量?
why i can't call a static member variable in an static member function like this?
大家好!有如下代码片段:
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;
}
当我点击"build"按钮时,输出信息是
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
但是,当我像这样更改代码位置时:
#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;
}
确实有效!
我不知道为什么?有人可以帮助我吗?
我的 IDE 是 vs pro 2015 + windows10.
您已声明 Test::b
但尚未定义。将此行添加到您的代码中(在测试之外 class)
int Test::b;
如果你愿意,你也可以给一个初始值
int Test::b = 123;
如何解决
使用 C++17
可以内联静态变量,这样就无需在 class.
之外定义它
static inline int i = 0; // I would also initialize it to zero, just to be sure
如果您不能使用 C++17
,则必须定义
int Test::b = 0; // Again I would also initialize it to zero, just to be sure
classTest
之外
原因
你写的时候
static void test()
{
static int b; // <-- definition is here
b = 3;
cout << b << endl;
}
你直接在class中定义了函数(这意味着它被自动标记为内联)。然后,您还可以在那里定义静态变量。如果它在函数范围之外,它只是一个声明(除非明确标记为内联 - 如上所示)。
相比之下,在另一种情况下,它在函数定义之外,因此您缺少静态变量的定义。
class Test {
public:
static int b ; // <-- only declaration - definition is missing
static void test()
{
b = 3;
cout << b<<endl;
}
};
针对 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;
}
};
修复 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;
}
其他answers专注于解决问题,而不是回答"why"部分。
当您在 class body 中定义一个函数时,它会自动被认为是 inline
并且任何数量的翻译单元(考虑 C++ 源代码)都可以定义它们。这就是您通常在 header 文件中定义函数的方式 - body 的函数将在多个来源中被 include
d。
当你只在classbody内声明一个函数,而在body外定义它时,它不会自动标记为inline
,这意味着包含这个定义的每个翻译单元将生成自己的强符号。在这种情况下,您通常将 header 文件中的声明与相关源文件中的实现分离,否则您会得到多个符号错误。 (即,如果您在 header 中有 non-inline 定义,则包含它们的每个源都会生成这些符号,并且链接器会感到困惑,因为它会看到来自不同来源的相同 non-inline 函数的多个版本)
现在,当您定义静态成员变量时,除非它是内联的,否则它还必须与翻译单元相关联。它类似于声明一个 extern
全局变量,也必须在某处定义。在你的情况下,你应该简单地添加:
int Test::b;
当您将定义与声明分离时,这一点更为重要。比如说,你有两个文件:
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;
}
符号(在本例中为全局变量 Test::b
和函数 Test::test
)与文件 Test.cpp 相关联并且仅生成一次。您可以在任意数量的源文件中包含 Test.hpp,并且不会生成额外的符号。
大家好!有如下代码片段: 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;
}
当我点击"build"按钮时,输出信息是
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
但是,当我像这样更改代码位置时:
#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;
}
确实有效! 我不知道为什么?有人可以帮助我吗? 我的 IDE 是 vs pro 2015 + windows10.
您已声明 Test::b
但尚未定义。将此行添加到您的代码中(在测试之外 class)
int Test::b;
如果你愿意,你也可以给一个初始值
int Test::b = 123;
如何解决
使用 C++17
可以内联静态变量,这样就无需在 class.
static inline int i = 0; // I would also initialize it to zero, just to be sure
如果您不能使用 C++17
,则必须定义
int Test::b = 0; // Again I would also initialize it to zero, just to be sure
classTest
原因
你写的时候
static void test()
{
static int b; // <-- definition is here
b = 3;
cout << b << endl;
}
你直接在class中定义了函数(这意味着它被自动标记为内联)。然后,您还可以在那里定义静态变量。如果它在函数范围之外,它只是一个声明(除非明确标记为内联 - 如上所示)。
相比之下,在另一种情况下,它在函数定义之外,因此您缺少静态变量的定义。
class Test {
public:
static int b ; // <-- only declaration - definition is missing
static void test()
{
b = 3;
cout << b<<endl;
}
};
针对 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;
}
};
修复 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;
}
其他answers专注于解决问题,而不是回答"why"部分。
当您在 class body 中定义一个函数时,它会自动被认为是 inline
并且任何数量的翻译单元(考虑 C++ 源代码)都可以定义它们。这就是您通常在 header 文件中定义函数的方式 - body 的函数将在多个来源中被 include
d。
当你只在classbody内声明一个函数,而在body外定义它时,它不会自动标记为inline
,这意味着包含这个定义的每个翻译单元将生成自己的强符号。在这种情况下,您通常将 header 文件中的声明与相关源文件中的实现分离,否则您会得到多个符号错误。 (即,如果您在 header 中有 non-inline 定义,则包含它们的每个源都会生成这些符号,并且链接器会感到困惑,因为它会看到来自不同来源的相同 non-inline 函数的多个版本)
现在,当您定义静态成员变量时,除非它是内联的,否则它还必须与翻译单元相关联。它类似于声明一个 extern
全局变量,也必须在某处定义。在你的情况下,你应该简单地添加:
int Test::b;
当您将定义与声明分离时,这一点更为重要。比如说,你有两个文件:
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;
}
符号(在本例中为全局变量 Test::b
和函数 Test::test
)与文件 Test.cpp 相关联并且仅生成一次。您可以在任意数量的源文件中包含 Test.hpp,并且不会生成额外的符号。