c++/结构的作用域

c++ / scope of struct

本文关键字:作用域 结构 c++      更新时间:2023-10-16

在下面的代码中,我认为结构stSameNameButDifferent是本地范围定义,所以没有问题。但我在运行时出错了。(错误:进程崩溃)

你能解释一下那个代码出了什么问题吗?

test_function.h

#ifndef TEST_FUNC_H_
#define TEST_FUNC_H_
void test_a();
void test_b();
#endif

main.cpp

#include <iostream>
#include "test_function.h"
using namespace std;
int main(int argc, const char** argv)
{
        cout << "testing for struct scope" << endl;
        test_a();
        test_b();
        return 0;
}

test_a.cpp

#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
        uint32_t nPlayCode;
        uint32_t nGameID;
        std::string sGameName;
};
void test_a()
{
        std::list<stSameNameButDifferent> lstSt;
        for(int i=0; i<10; ++i)
        {
                stSameNameButDifferent st;
                st.nPlayCode = i;
                st.nGameID = 100+i;
                std::ostringstream osBuf;
                osBuf << "Game_" << i;
                st.sGameName = osBuf.str();
                lstSt.push_back(st);
        }
        for(auto &st : lstSt)
        {
                std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
        }
}

test_b.cpp

#include <iostream>
#include <sstream>
#include <cstdint>
#include <list>
#include "test_function.h"
struct stSameNameButDifferent
{
        uint32_t nPlayCode;
        uint32_t nGameID;
        float    fDiscountRate;
        std::string sGameName;
};
void test_b()
{
        std::list<stSameNameButDifferent> lstSt;
        for(int i=0; i<10; ++i)
        {
                stSameNameButDifferent st;
                st.nPlayCode = i;
                st.nGameID = 1000+i;
                st.fDiscountRate = (float)i/100;
                std::ostringstream osBuf;
                osBuf << "Game_" << i;
                st.sGameName = osBuf.str();
                lstSt.push_back(st);
        }
        for(auto &st : lstSt)
        {
                std::cout << st.nPlayCode << ", " << st.nGameID << ", " << st.sGameName << std::endl;
        }
}

为了避免相同的struct名称在多个翻译单元中发生冲突,您必须将它们放在一个未命名的命名空间中,如下所示:

namespace {
    struct stSameNameButDifferent {
        uint32_t nPlayCode;
        uint32_t nGameID;
        std::string sGameName;
    };
}

这将使得stSameNameButDifferent仅在相应的翻译单元(.cpp文件)中被私下看到。

否则,链接器将使用找到的第一个符号来解析该符号,从而导致您在运行时看到的错误。

您已经在全局范围内定义了stSameNameButDifferent,因此编译器无法将两个定义都查看和分析到同一个struct,并且只会获取它遇到的第一个定义,这就是为什么会出现错误。

您可以为test_atest_b使用两个不同的名称空间,因此不会出现任何错误。