【问题标题】:How the accessbility of a class or function in C++ is controlled如何控制 C++ 中类或函数的可访问性
【发布时间】:2026-02-06 14:45:01
【问题描述】:

使用 C# 等语言。你可以把public或者internal放在一个类的前面来控制一个类的访问级别。这是如何在 C++ DLL 中完成的?

【问题讨论】:

  • 都是头文件。
  • 你的意思是如果用户包含一个头文件,连同一个静态库或DLL,他将始终能够访问一个类。
  • 外部类都是隐式公开的(对于内部类,请参见 Bar Siete 的回答)。
  • 对于 C++ dll 的事情要复杂得多。实际上,默认情况下一切都是内部的,除非您使用特殊的编译器标志将其标记为需要“导出”。 exe使用的标头还需要知道标头中的内容必须从dll“导入”。

标签: c++ public


【解决方案1】:

大概您基本上是在问如何从 DLL 中导出类。

在这种情况下,大多数 Windows 编译器(例如 VC++、MinGW)使用__declspec(dllexport) 来完成这项工作。

为了反映这一点,客户端代码需要将类声明为__declspec(dllimport)。通常你会得到类似的结果:

#ifdef BUILD_DLL
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif

DLL class whatever { 
    // ...
};

...在头文件中,然后用于构建 DLL 的 make 文件将定义 BUILD_DLL:

cflags += /DBUILD_DLL

【讨论】:

    【解决方案2】:

    通过将一个类嵌套在另一个类中:

    class A
    {
    public:
        class B {};
    protected:
        class C {};
    private:
        class D {};
    };
    

    【讨论】:

      【解决方案3】:

      与 C#(或任何其他现代语言)不同,C++ 语言标准不涉及动态库/共享对象的任何内容。

      因此,语言/编译器实现者定义自己的跨 DLL/SO 导出类定义的方式都是特定于语言/编译器的。

      更多信息请参考http://gcc.gnu.org/wiki/Visibility

      #if defined _WIN32 || defined __CYGWIN__
        #ifdef BUILDING_DLL
          #ifdef __GNUC__
            #define DLL_PUBLIC __attribute__ ((dllexport))
          #else
            #define DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
          #endif
        #else
          #ifdef __GNUC__
            #define DLL_PUBLIC __attribute__ ((dllimport))
          #else
            #define DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
          #endif
        #endif
        #define DLL_LOCAL
      #else
        #if __GNUC__ >= 4
          #define DLL_PUBLIC __attribute__ ((visibility ("default")))
          #define DLL_LOCAL  __attribute__ ((visibility ("hidden")))
        #else
          #define DLL_PUBLIC
          #define DLL_LOCAL
        #endif
      #endif
      
      extern "C" DLL_PUBLIC void function(int a);
      class DLL_PUBLIC SomeClass
      {
         int c;
         DLL_LOCAL void privateMethod();  // Only for use within this DSO
      public:
         Person(int _c) : c(_c) { }
         static void foo(int a);
      }; 
      

      从上面的 sn-p 可以看出,导出类直接依赖于编译器特定的扩展。

      CL/MSVC - __declspec(dllexport), __declspec(dllimport
      GCC - __attribute__ ((visibility ("default")))
      

      GCC 还提供 **-fvisibility=[hidden|default] 以更好地控制通过 DLL/SO 导出的符号。

      【讨论】: