大家!有一个如下代码片段: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;
}
当我点击“构建”按钮时,输出消息是
错误LNK2001:未解析的外部符号“public:static int Test :: b”(?b @ Test @@ 2HA)1> B:\ PROGRAMPROJECT \ visual 2015 pro \ testcase \ testcase \ x64 \ Debug \ testcase.exe:致命错误LNK1120:1个未解析的外部
但是,当我更改代码位置时,如下所示:
#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。
如何解决它
使用C++17
,您可以内联静态变量,从而无需在类外部定义它。
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
课外Test
为什么呢
你写的时候
static void test()
{
static int b; // <-- definition is here
b = 3;
cout << b << endl;
}
您直接在类中定义了该函数(这意味着它自动标记为内联)。然后,您还可以在那里定义静态变量。如果它在函数范围之外,它只是一个声明(除非明确标记为内联 - 如上所示)。
相反,在另一种情况下,它在函数定义之外,因此您缺少静态变量的定义。
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;
}
其他的重点是解决问题,而不是回答“为什么”的部分。
当你在类体中定义一个函数时,它会自动被认为是inline
,任何数量的翻译单元(想想C ++源代码)都可以定义它们。这就是你通常在头文件中定义函数的方式 - 一个函数,它的主体将是多个源中的include
d。
当您只在类体内声明一个函数,但在外部定义它时,它不会自动标记为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,并且不会生成其他符号。
有关参考,请参阅qazxsw poi
你已经宣布了https://en.cppreference.com/w/cpp/language/static,但你没有定义它。将此行添加到您的代码中(在Test类之外)
Test::b
如果您愿意,也可以给出初始值
int Test::b;