簡體   English   中英

為什么我不能在這樣的靜態成員函數中調用靜態成員變量?

[英]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,並且不會生成其他符號。

有關參考,請參閱https://en.cppreference.com/w/cpp/language/static

您已聲明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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM