C++中相当于C#的internal关键字

27

我正在尝试将一些C#代码回溯到C++,以解决一个令人讨厌的问题,想问一下是否有人知道C++中与C#的'internal'相当的等效语法。

下面是使用它的示例:

internal int InternalArray__ICollection_get_Count ()
        {
            return Length;
        }

我不确定是否有直接的等价物,但friend函数可能比较接近。(话说,我对最新的 C++ 版本并不完全了解。) - millimoose
1
我会考虑使用PIMPL惯用语。 - Arafangion
@Arafangion 那会有所帮助,但是你就无法在模块内获得更快的编译速度了,除非你使用多层次的那些。 (这又增加了更多样板文件。尽管显然可以通过这个来解决:http://c2.com/cgi/wiki?PimplIdiom) - millimoose
@millimoose: 尽管如此,您将获得应用程序或库的整体更快的编译速度,并且您不需要多个层。只需在头文件类中使用“class Impl; std::unique_ptr<Impl> impl;”即可。 - Arafangion
3个回答

30

internal在C++中没有直接的等效物。除了public/protected/private之外,唯一的访问控制机制是friend,这是一种允许特定类访问自己类中所有成员的机制。

因此,它可以被用作类似internal的访问控制机制,但主要区别在于:

  • 您必须逐个显式声明friend
  • friend类可以无例外地访问所有成员;这是一种极高级别的访问权限,可能会引入紧密耦合(这就是为什么对friend的惯常反应是"你真的需要吗?")

另请参见在C++中何时使用'friend'?


使用C++/CLI,一个访问修饰符定义了程序集内的访问权限,另一个则定义了程序集外的访问权限。顺序无关紧要:更多的访问权限总是来自内部。在C#中,internal使用C++/CLI的public private实现:程序集内为public,程序集外为private。在C#中,无法实现程序集内为protected,程序集外为private,但在C++/CLI中可以实现。详情请见:http://weblogs.thinktecture.com/cnagel/2004/12/access-modifiers-ccli-vs-c-vs-vb.html - user978122
似乎将公共的声明为私有的是正确的方法,但我无法理解它的意义。很抱歉这么愚蠢,你能向我解释一下吗? - user978122
1
如果您正在使用C++/CLI,则应在问题中明确提到(不幸的是我没有经验,因此无法在那里提出一个好的解决方案)。否则,您引用的内容不适用。 - Jon
嗯,看起来 C++/CLI 不是我想象的那样。不管了,我会根据需要将所有内容更改为 public 或 protected。 - user978122
请注意,您还可以与特定的函数建立友好关系。 - Sebastian Mach

5
如果您想将整个模块相互隔离,可以尝试保持两组头文件——一组包含“公共”方法,另一组包含“内部”方法。但我不确定如何在该点上避免重复;据我所知,在编译单元中,一个类只能声明一次,并且公共和内部头需要一个完整的类定义。一种笨拙的方法是使用类似_Foo.public.h_Foo.internal.h这样的部分文件,它们只包含方法声明,而“真实”的头文件将其中一个或两个包含到类声明体中:

Foo.public.h

class Foo {
    #include "_foo.public.h"
}

Foo.internal.h

class Foo {
    #include "_foo.internal.h"
}

源文件会引用自己模块的内部头文件,但是会引用它们所依赖的公共头文件。可以通过调整项目布局和构建脚本来使这一过程相对透明化(例如,为每个模块设置正确的包含路径)。

这仅仅是隐藏了“内部”成员,而没有实现实际的访问控制,因此假设模块被单独编译并作为二进制依赖项处理。如果您通过将依赖项包含在源代码树中并一次性编译所有内容来处理依赖项,则无论如何都需要构建它们,并且内部方法声明可能仍然存在于构建中。


1
在标准C++中,这是完全禁止的(请参阅:一个定义规则)。你可能可以在某些特定环境下得逞,但更好的模式是将公共部分作为私有(完整)实现的基类。 - Ben Voigt

0

对于仍然感兴趣的人,我认为有一个宏解决方案。通常在创建API时,我会在API项目的设置中定义一个“BUILDDLL”宏,用于定义DLL的导出/导入,如下所示:

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

所以我也使用它来定义一个INTERNAL宏:

#ifdef BUILDDLL
    #define INTERNAL public
#else
    #define INTERNAL private
#endif

BUILDDLL 在 DLL 项目的设置中被定义(在 VS 中,属性->C\C++->预处理器->预处理器定义),但不在使用该库的项目的设置中。因此对于使用该库的项目,这个宏会被替换成“private”,但在 DLL 项目内部则为“public”。您可以像使用其他访问修饰符一样使用它:

class DLL Foo
{
public:
    int public_thing;
INTERNAL:
    int internal_thing;
};

这不是一个完美的解决方案(例如,您不能将其与定义出现在头文件中的成员函数一起使用,而且没有阻止最终用户覆盖它),但似乎可以正常工作。我认为它适用于宏的“好”用法之一,并且对于查看代码的外部人员(熟悉C#关键字的人)来说,它的含义非常清晰。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接