[英]Why can't a static constexpr member variable be passed to a function?
[英]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;
}
當我單擊“構建”按鈕時,輸出消息是
錯誤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。
其他答案集中於解決問題,而不是回答“為什么”部分。
當您在類主體中定義一個函數時,它會自動被認為是inline
函數,並且任何數量的翻譯單元(例如C ++源代碼)都可以定義它們。 那就是您通常在頭文件中定義函數的方式-主體的函數將include
在多個源中。
當您僅在類主體中聲明一個函數而在外部定義它時,該函數不會自動標記為inline
,這意味着包含此定義的每個翻譯單元都會生成自己的強符號。 在這種情況下,通常會將頭文件中的聲明與關聯的源文件中的實現解耦,否則會出現多個符號錯誤。 (即,如果標頭中包含非內聯定義,則包含它們的每個源都會生成這些符號,並且鏈接器會感到困惑,因為它會看到同一非內聯函數的多個版本來自不同的源)
現在,當您定義靜態成員變量時,除非它是內聯的,否則還必須與翻譯單元關聯。 類似於聲明extern
全局變量,該變量也必須在某處定義。 對於您的情況,您只需添加:
int Test::b;
將定義與聲明解耦時,這一點更為重要。 假設您有兩個文件:
測試文件
class Test {
public:
static int b ;
static void test();
};
測試文件
#include "Test.hpp"
int Test::b;
void Test::test()
{
b = 3;
cout << b<<endl;
}
這些符號(在這種情況下,是全局變量Test::b
和函數Test::test
)與文件Test.cpp相關聯,並且僅生成一次。 您可以在任意數量的源文件中包含Test.hpp,並且不會生成其他符號。
您已聲明Test::b
但尚未定義它。 將此行添加到您的代碼中(Test類之外)
int Test::b;
您也可以根據需要提供初始值
int Test::b = 123;
如何解決
使用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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.