C++跨模块访问类中静态成员变量

C++访问跨模块类中静态成员变量

0. 结论

在C++中,无法直接访问跨模块类中的静态变量成员,必须通过静态方法访问。

1. 示例

为了说明此问题,示例源码如下:

1.1 文件结构

文件结构如下图:

1.2 文件内容

1.2.1 工程CMakeLists.txt

工程的CMakeLists.txt(即F:\learn_cmake目录下的):

cmake_minimum_required(VERSION 3.18)

## 设置工程名称
set(PROJECT_NAME KZN)

## 设置工程版本号
set(PROJECT_VERSION "1.0.1.0" CACHE STRING "默认版本号")

## 工程定义
project(${PROJECT_NAME}
    LANGUAGES CXX C
    VERSION ${PROJECT_VERSION}
)

## 配置默认构建类型
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "默认构建类型")
endif()

## 通过空指针字节数来判断运行平台(即64或32位系统) 
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
    set(${PROJECT_NAME}_PLATFORM_NAME "x64")
else()
    set(${PROJECT_NAME}_PLATFORM_NAME "Win32")
endif()

## 打印选项ACCESS_STATIC_MEMBER的值
message(STATUS "ACCESS_STATIC_MEMBER:${ACCESS_STATIC_MEMBER}")
## 若为真,则添加定义源文件的预处理符号
if(ACCESS_STATIC_MEMBER)
    ## 添加源文件预处理符号ACCESS_STATIC_MEMBER
    ## 添加源文件预处理符号:控制是否直接访问静态成员变量
	## 在代码中将使用此宏
    ##add_definitions("-DACCESS_STATIC_MEMBER")
endif()

## 打印选项ACCESS_STATIC_FUNCTION的值
message(STATUS "ACCESS_STATIC_FUNCTION:${ACCESS_STATIC_FUNCTION}")
## 若为真,则添加定义源文件的预处理符号
if(ACCESS_STATIC_FUNCTION)
    ## 添加源文件预处理符号ACCESS_STATIC_FUNCTION
	## 作用:控制是否通过访问静态成员函数以访问静态成员变量
	## 在代码中将使用此宏
    add_definitions("-DACCESS_STATIC_FUNCTION")
endif()

## 禁止RelWithDebInfo的优化
if(MSVC)
    ## 打印替换前的值
    message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO_Before_Replace:${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
    ## 将字符串CMAKE_CXX_FLAGS_RELWITHDEBINFO中的/O2使用/Od进行替换,然后替换后的结果再存入CMAKE_CXX_FLAGS_RELWITHDEBINFO
    STRING(REPLACE "/O2" "/Od" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
	## 打印替换后的值
	message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO_After_Replace:${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
endif()

## 控制VS工程生成使用"文件夹"组织结构
set_property(GLOBAL PROPERTY USE_FOLDERS ON)

## 定义选项:KZN_DEVELOPE_MODE开发模式开关
option(${PROJECT_NAME}_DEVELOPE_MODE "开发模式" ON)

## 开发者模式,统一输出目录,防止本地运行时发生缺少动态库的错误
## 一般都是在根目录CMakeLists.txt中定义,如果子目录中没有指定输出目录,则沿用父目录指定的输出目录
if(${PROJECT_NAME}_DEVELOPE_MODE)
    ## 开发者模式下统一执行程序的输出目录
    if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY)
        set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
    endif()
    
	## 开发者模式下统一动态库的输出目录
	if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY)
        set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/$<CONFIG>")
    endif()
endif()

## 定义工程源代码目录变量
set(PROJECT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")

## 定义运行时输出目录,可以另外自定义目录
#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/build/KZN/build")

## 打印默认构建类型 
message(STATUS "DEFAULT_CMAKE_CONFIGURATION_TYPES:${CMAKE_CONFIGURATION_TYPES}")
if(${PROJECT_NAME}_DEVELOPE_MODE)
    ## 开发者模式下,配置构建类型列表(注意此处仅仅配置RelWithDebInfo)
    set(CMAKE_CONFIGURATION_TYPES RelWithDebInfo)
endif()

## 添加子目录
add_subdirectory(libs)  ## 业务模块库
add_subdirectory(src)   ## 主程序库

## 设置默认启动工程
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT KZN2024)

1.2.2 模块库(libs)
1.2.2.1 模块库CMakeLists.txt

模块库的CMakeLists.txt(即F:\learn_cmake\libs目录下的):

add_subdirectory(common)
add_subdirectory(module_a)
1.2.2.2 公共模块(common)

公共模块头文件:

  1. kznadd.h

    // kznadd.h
    #pragma once
    
    #ifndef KZN_ADD_H
    #define KZN_ADD_H
    
    #include <string>
    
    struct KZNInfo
    {
        int nType = 0;
        double dCount = 0.0;
        std::string sName;
    };
    
    class KZNAdd
    {
    public:
        // 公共访问权限的静态成员函数
        static int add(int a, int b);
    
        // 公共访问权限的静态成员函数
        static KZNInfo oInfo();
    
    public:
        // 公共访问权限的静态成员对象
        static KZNInfo m_s_oInfo;
    };
    
    #endif // KZN_ADD_H
    
  2. kznapp.h

    // kznapp.h
    #pragma once
    
    #ifndef KZN_APP_H
    #define KZN_APP_H
    
    class KZNApp
    {
    public:
        void exec(int a, int b);
    };
    
    #endif // KZN_APP_H
    

公共模块源文件:

  1. kznadd.cpp

    // kznadd.cpp
    #include "kznadd.h"
    
    // 初始化类中静态成员变量
    KZNInfo KZNAdd::m_s_oInfo = KZNInfo{};
    
    int KZNAdd::add(int a, int b)
    {
        return (a + b);
    }
    
    KZNInfo KZNAdd::oInfo()
    {
        return m_s_oInfo;
    }
    
  2. kznapp.cpp

    // kznapp.cpp
    #include "kznadd.h"
    #include "kznapp.h"
    
    void KZNApp::exec(int a, int b)
    {
    #ifdef ACCESS_STATIC_MEMBER
        // 此项目内,直接访问类的静态成员对象值:正常
        auto oInfoByMember = KZNAdd::m_s_oInfo;
    #endif
    
    #ifdef ACCESS_STATIC_FUNCTION
        // 此项目内,通过访问类的静态成员函数,读取类的静态成员对象值:正常
        auto oInfoByFunc = KZNAdd::oInfo();
    #endif
    }
    

公共模块的CMakeLists.txt文件:

  • CMakeLists.txt

    cmake_minimum_required(VERSION  3.15)
    
    ##设置target名称
    set(TARGET_NAME KZNCommon)
    
    ##设置源代码路径
    set(${TARGET_NAME}_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
    
    ##提取当前模块所有源文件(include和src分开提取)
    file(GLOB_RECURSE ${TARGET_NAME}_HEADER_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/include/*.h*"
    )
    
    file(GLOB_RECURSE ${TARGET_NAME}_SRC_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/src/*.h*"
        "${${TARGET_NAME}_SOURCE_DIR}/src/*.c*"
    )
    
    ##为VS设置源代码文件夹
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}/include"
        PREFIX "Header Files"
        FILES ${${TARGET_NAME}_HEADER_FILES}
    )
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}/src/"
        PREFIX "Source Files"
        FILES ${${TARGET_NAME}_SRC_FILES}
    )
    
    ##添加target及别名
    add_library(${TARGET_NAME} SHARED) ## 动态库
    add_library(${PROJECT_NAME}::${TARGET_NAME} ALIAS ${TARGET_NAME}) ## 定义别名
    
    ##指定源文件
    target_sources(${TARGET_NAME}
        PRIVATE  ${${TARGET_NAME}_SRC_FILES}
        PRIVATE  ${${TARGET_NAME}_HEADER_FILES}
    )
    
    ##设置target属性
    set_target_properties(${TARGET_NAME} PROPERTIES
        WINDOWS_EXPORT_ALL_SYMBOLS  True  ##自动导出符号
        FOLDER  "libs/common"  ##设置VS路径
    )
    
    ##设置预处理器定义
    if(MSVC)
        target_compile_definitions(${TARGET_NAME} PRIVATE UNICODE NOMINMAX)
        ##解决C++17情况下std::byte引起的编译错误(主要是不正确使用std命名空间导致)
        target_compile_definitions(${TARGET_NAME} PRIVATE "_HAS_STD_BYTE=0") 
        ##解决C++17情况下使用std::auto_ptr引起的编译错误
        target_compile_definitions(${TARGET_NAME} PRIVATE "_HAS_AUTO_PTR_ETC=1")
    endif()
    
    ##配置构建/使用时的头文件路径
    target_include_directories(
        ${TARGET_NAME}
        PUBLIC
          "$<BUILD_INTERFACE:${${TARGET_NAME}_SOURCE_DIR}/include>"
          "$<INSTALL_INTERFACE:include>"
        PRIVATE
          "$<BUILD_INTERFACE:${${TARGET_NAME}_SOURCE_DIR}/src>"
    )
    
1.2.2.3 模块A(module_a)

模块A头文件:

  1. kznservice.h

    // kznservice.h
    #pragma once
    
    #ifndef KZN_SERVICE_H
    #define KZN_SERVICE_H
    
    class KZNService
    {
    public:
        static void exec(int a, int b);
    };
    
    #endif // KZN_SERVICE_H
    

模块A源文件:

  1. kznservice.cpp

    // kznservice.cpp
    #include "kznservice.h"
    #include "kznadd.h"
    
    void KZNService::exec(int a, int b)
    {
    #ifdef ACCESS_STATIC_MEMBER
        // 访问依赖项目common中KZNAdd类的静态成员对象值:错误
        auto oInfoByMember = KZNAdd::m_s_oInfo; // error:无法解析的外部符号
    #endif
    
    #ifdef ACCESS_STATIC_FUNCTION
        // 访问依赖项目common中KZNAdd类的静态成员函数(间接读取类的静态成员对象值):正常
        auto oInfoByFunc = KZNAdd::oInfo();
        // 访问依赖项目common中KZNAdd类的普通成员函数:正常
        auto result = KZNAdd::add(a, b);
    #endif
    }
    

模块A的CMakeLists.txt文件:

  • CMakeLists.txt

    cmake_minimum_required(VERSION  3.15)
    
    ## 设置target名称
    set(TARGET_NAME KZNModuleA)
    
    ## 设置源代码路径
    set(${TARGET_NAME}_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
    
    ## 提取当前模块所有源文件(include和src分开提取)
    file(GLOB_RECURSE ${TARGET_NAME}_HEADER_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/include/*.h*"
    )
    
    file(GLOB_RECURSE ${TARGET_NAME}_SRC_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/src/*.h*"
        "${${TARGET_NAME}_SOURCE_DIR}/src/*.c*"
    )
    
    ## 为VS设置源代码文件夹
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}/include"
        PREFIX "Header Files"
        FILES ${${TARGET_NAME}_HEADER_FILES}
    )
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}/src/"
        PREFIX "Source Files"
        FILES ${${TARGET_NAME}_SRC_FILES}
    )
    
    ## 添加target及定义别名
    add_library(${TARGET_NAME} SHARED) ## 动态库
    add_library(${PROJECT_NAME}::${TARGET_NAME} ALIAS ${TARGET_NAME}) ## 定义别名
    
    ## 指定target的源文件
    target_sources(${TARGET_NAME}
        PRIVATE ${${TARGET_NAME}_SRC_FILES}
        PRIVATE ${${TARGET_NAME}_HEADER_FILES}
    )
    
    ## 设置target属性
    set_target_properties(${TARGET_NAME} PROPERTIES
        WINDOWS_EXPORT_ALL_SYMBOLS True  ## 自动导出符号
        FOLDER "libs/module_a"  ## 设置VS源码文件夹
    )
    
    ## 设置预处理器定义
    if(MSVC)
        target_compile_definitions(${TARGET_NAME} PRIVATE UNICODE NOMINMAX)
        ##解决C++17情况下std::byte引起的编译错误(主要是不正确使用std命名空间导致)
        target_compile_definitions(${TARGET_NAME} PRIVATE "_HAS_STD_BYTE=0")
        ##解决C++17情况下使用std::auto_ptr引起的编译错误
        target_compile_definitions(${TARGET_NAME} PRIVATE "_HAS_AUTO_PTR_ETC=1")      
    endif()
    
    ## 配置构建/使用时的头文件路径
    target_include_directories(
        ${TARGET_NAME}
        PUBLIC
          "$<BUILD_INTERFACE:${${TARGET_NAME}_SOURCE_DIR}/include>"
          "$<INSTALL_INTERFACE:include>"
        PRIVATE
          "$<BUILD_INTERFACE:${${TARGET_NAME}_SOURCE_DIR}/src>"
    )
    
    ## 设置链接依赖库
    target_link_libraries(${TARGET_NAME} KZN::KZNCommon)
    
1.2.3 主程序(src)
1.2.3.1 主程序CMakeLists.txt

主程序CMakeLists.txt,(即F:\learn_cmake\src目录下的):

add_subdirectory(kaizen)
1.2.3.2 主程序文件(kaizen)

主程序头文件:

  1. stdafx.h

    // stdafx.h : 标准系统包含文件的包含文件,
    // 或是经常使用但不常更改的
    // 特定于项目的包含文件
    //
    #pragma once
    // Windows 头文件:
    #include <windows.h>
    #include <tuple>
    #include <memory>
    // std库
    #include <set>
    #include <vector>
    #include <map>
    #include <hash_map>
    #include <hash_set>
    #include <functional>
    #include <algorithm>
    #include <string.h>
    #include <strstream>
    #include <assert.h>
    #include <iostream>
    #include <memory>
    

主程序源文件:

  1. stdafx.cpp

    #include "stdafx.h"
    
  2. main.cpp

    #include "stdafx.h"
    
    #include "kznadd.h"
    #include "kznservice.h"
    
    int main(int argc, char *argv[])
    {
    #ifdef ACCESS_STATIC_MEMBER
        // 访问依赖项目common中KZNAdd类的静态成员对象值:错误
        auto oInfoByMember = KZNAdd::m_s_oInfo; // error无法解析的外部符号
    #endif
    
    #ifdef ACCESS_STATIC_FUNCTION
        // 访问依赖项目common中KZNAdd类的静态成员函数(间接读取依赖项目类的静态成员对象值):正常
        auto oInfoByFunc = KZNAdd::oInfo();
    #endif
    
        return 0;
    }
    

主程序的CMakeLists.txt文件:

  • CMakeLists.txt

    cmake_minimum_required(VERSION  3.15)
    
    ##设置target名称
    set(TARGET_NAME KZN2024)
    
    ##设置源代码路径
    set(${TARGET_NAME}_SOURCE_DIR  ${CMAKE_CURRENT_SOURCE_DIR})
    
    ##提取所有源文件(include与src区分开)
    file(GLOB_RECURSE  ${TARGET_NAME}_HEADER_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/*.h*"
    )
    
    file(GLOB_RECURSE  ${TARGET_NAME}_SRC_FILES
        LIST_DIRECTORIES False CONFIGURE_DEPENDS
        "${${TARGET_NAME}_SOURCE_DIR}/*.h*"
        "${${TARGET_NAME}_SOURCE_DIR}/*.c*"
    )
    
    ##为VS设置源代码文件夹
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}"
        PREFIX "Header Files"
        FILES ${${TARGET_NAME}_HEADER_FILES}
    )
    source_group(
        TREE "${${TARGET_NAME}_SOURCE_DIR}"
        PREFIX "Source Files"
        FILES ${${TARGET_NAME}_SRC_FILES}
    )
    
    ##指定源文件
    add_executable(${TARGET_NAME}
        ${${TARGET_NAME}_SRC_FILES}
        ${${TARGET_NAME}_HEADER_FILES}
    )
    
    ## 设置链接器-系统-子系统
    ## VS->属性页->链接器->系统->子系统->/SUBSYSTEM:CONSOLE
    ##set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE") ## /SUBSYSTEM:WINDOWS
    ##set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:WINDOWS") ## /SUBSYSTEM:WINDOWS
    message(STATUS "CMAKE_EXE_LINKER_FLAGS:${CMAKE_EXE_LINKER_FLAGS}")
    
    set_target_properties(${TARGET_NAME} PROPERTIES
       ## WIN32_EXECUTABLE ON  ## 设置Win32可执行程序
    	LINK_FLAGS "/SAFESEH:NO /LARGEADDRESSAWARE"
        FOLDER  "plugins" ## 设置工程的VS代码路径
    )
    
    ##设置库导出
    if(MSVC)
        message(STATUS "KZN_PLATFORM_NAME:${${PROJECT_NAME}_PLATFORM_NAME}")
        if(${${PROJECT_NAME}_PLATFORM_NAME} STREQUAL "x64")
            target_compile_definitions(${TARGET_NAME} PRIVATE WIN64)
        endif()
    endif()
    
    target_compile_definitions(${TARGET_NAME} PRIVATE UNICODE _UNICODE NOMINMAX _SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS)
    
    ##配置构建/使用时的头文件路径
    target_include_directories(${TARGET_NAME}
        PRIVATE
        "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
    )
    
    ##配置库依赖
    target_link_libraries(${TARGET_NAME}
        PRIVATE KZN::KZNCommon KZN::KZNModuleA
    )
    
1.2.4 CMake
1.2.4.1 cmake_config_vs_2015.bat

专供VS2015配置使用的CMake脚本:

rem cmake_config_vs_2015.bat

@echo off

set currentDir=%~dp0
echo bat_script_path:%currentDir%

cd ..\
set sourceDir=%cd%
echo source_code_path:%sourceDir%

set cmakeOutputDir=%sourceDir%\build
echo cmake_output_path:%cmakeOutputDir%

cmake -S %sourceDir% -B %cmakeOutputDir% -G"Visual Studio 14 2015" -A x64

pause
1.2.4.2 cmake_config_vs_2019.bat

专供VS2019配置使用的CMake脚本:

rem cmake_config_vs_2019.bat

@echo off

set currentDir=%~dp0
echo bat_script_path:%currentDir%

cd ..\
set sourceDir=%cd%
echo source_code_path:%sourceDir%

set cmakeOutputDir=%sourceDir%\build
echo cmake_output_path:%cmakeOutputDir%

cmake -S %sourceDir% -B %cmakeOutputDir% -G"Visual Studio 16 2019" -T v140 -A x64

pause
1.2.4.3 cmake_config_vs_2022.bat

专供VS2022配置使用的CMake脚本:

rem cmake_config_vs_2022.bat

@echo off

set currentDir=%~dp0
echo bat_script_path:%currentDir%

cd ..\
set sourceDir=%cd%
echo source_code_path:%sourceDir%

set cmakeOutputDir=%sourceDir%\build
echo cmake_output_path:%cmakeOutputDir%

cmake -S %sourceDir% -B %cmakeOutputDir% -G"Visual Studio 17 2022" -T v140 -A x64 -DACCESS_STATIC_FUNCTION=ON -DACCESS_STATIC_MEMBER=OFF

pause

1.3 build目录

根据安装VS的版本,执行对应的bat脚本程序,即可在代码同目录生成build文件夹。

build编译文件与源码文件完全隔离开,防止源码被影响。

比如,本地安装VS2022,执行cmake_config_vs_2022.bat脚本。

生成解决方案sln如下过程:

F:\learn_cmake\cmake>rem cmake_config_vs_2022.bat
bat_script_path:F:\learn_cmake\cmake\
source_code_path:F:\learn_cmake
cmake_output_path:F:\learn_cmake\build
-- Selecting Windows SDK version 10.0.22621.0 to target Windows 10.0.22631.
-- The CXX compiler identification is MSVC 19.0.24247.2
-- The C compiler identification is MSVC 19.0.24247.2
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio 14.0/VC/bin/amd64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- ACCESS_STATIC_MEMBER:OFF
-- ACCESS_STATIC_FUNCTION:ON
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO_Before_Replace:/Zi /O2 /Ob1 /DNDEBUG
-- CMAKE_CXX_FLAGS_RELWITHDEBINFO_After_Replace:/Zi /Od /Ob1 /DNDEBUG
-- DEFAULT_CMAKE_CONFIGURATION_TYPES:Debug;Release;MinSizeRel;RelWithDebInfo
-- CMAKE_EXE_LINKER_FLAGS:/machine:x64
-- KZN_PLATFORM_NAME:x64
-- Configuring done (4.9s)
-- Generating done (0.0s)
-- Build files have been written to: F:/learn_cmake/build
请按任意键继续. . .

1.4 解决方案

打开解决方案KZN.sln,如下图示:

2. 解析

  • CMAKE_RUNTIME_OUTPUT_DIRECTORY

    CMAKE_RUNTIME_OUTPUT_DIRECTORY:二进制执行文件exe输出目录

    CMAKE_LIBRARY_OUTPUT_DIRECTORY:二进制动态库文件dll输出目录

    CMAKE_ARCHIVE_OUTPUT_DIRECTORY:静态库文件lib输出目录

    以上三者,一般都是在根目录CMakeLists.txt中定义,如果子目录中没有指定输出位置,则沿用父目录指定的输出位置

    若不定义CMAKE_RUNTIME_OUTPUT_DIRECTORY,则从target的RUNTIME_OUTPUT_DIRECTORY属性中读取不到内容。

    若不定义CMAKE_LIBRARY_OUTPUT_DIRECTORY,则从target的LIBRARY_OUTPUT_DIRECTORY属性中读取不到内容。

  • cmake_config_vs_2022.bat

    此脚本中,-DACCESS_STATIC_FUNCTION=ON表示定义选项ACCESS_STATIC_FUNCTION且值为ON,即打开开关。 -DACCESS_STATIC_MEMBER=OFF表示定义选项ACCESS_STATIC_MEMBER且值为OFF,即关闭。

  • 理解CMake控制源码预处理符号的逻辑

    通过CMake选项ACCESS_STATIC_FUNCTION控制CMakeLists.txt中是否添加定义预处理器符号,从而控制源码的预处理执行逻辑。

3. 总结

默认执行vmake_config_vs_2022.bat脚本,然后使用VS2022打开KZN.sln可以编译通过。

若将-DACCESS_STATIC_MEMBER=ON开关打开后,再执行vmake_config_vs_2022.bat脚本,然后使用VS2022编译解决方案,VS会报错误。根据错误提示内容,可以琢磨理解此篇主题。

即在C++中,无法直接访问跨模块类中的静态变量成员,必须通过静态方法访问。

posted @ 2024-07-16 23:19  kaizenly  阅读(121)  评论(0编辑  收藏  举报
打赏