C++ 等价于 C# 的内部

Posted

技术标签:

【中文标题】C++ 等价于 C# 的内部【英文标题】:C++ equivalent of C#'s internal 【发布时间】:2012-12-05 11:54:58 【问题描述】:

我正在尝试将一些代码从 C# 反向移植到 C++ 以解决一个烦人的问题,并且想问是否有人知道 C# 的“内部”在 C++ 中的等价物是什么。

这是一个使用它的例子:

internal int InternalArray__ICollection_get_Count ()
        
            return Length;
        

【问题讨论】:

我不确定是否有直接的等价物,但friend functions 可能很接近。 (也就是说,我并不完全了解最新的 C++ 版本。) 我会考虑使用 PIMPL 成语。 @Arafangion 这会有所帮助,但是除非您使用多层,否则您将无法在模块内获得更快编译的好处。 (这增加了更多样板。虽然显然可以通过:c2.com/cgi/wiki?PimplIdiom) @millimoose:不过,您可以更快地编译整个应用程序或库,并且不需要多层。只是一个 Impl 类; std::unique_ptr impl;在标题类中会很好。 【参考方案1】:

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

因此它可以用作internal-like 的访问控制机制,最大的区别在于:

您必须一个一个地显式声明friendfriend 类无一例外地可以访问所有成员;这是一个极高级别的访问,并且会引入紧密耦合(这就是为什么对friend 的习惯反应是“你真的需要那个吗?”)

另见When should you use 'friend' in C++?

【讨论】:

"在 C++/CLI 中,一个访问修饰符定义程序集中的访问,另一个定义外部访问。顺序无关紧要:更多的访问总是来自内部。C# 内部是用C++/CLI 公有私有:程序集内的公共,程序集外的私有。在程序集内受保护和在程序集外私有在 C# 中是不可能的,但在 C++/CLI 中是可能的。 weblogs.thinktecture.com/cnagel/2004/12/… 似乎声明公有私有是要走的路,但我无法理解它。很抱歉这么愚蠢,但可以向我解释一下吗? @user978122:如果您使用的是 C++/CLI,那么您应该在问题中明确提及这一点(不幸的是,我没有这方面的经验,因此无法在那里提出一个好的解决方案)。否则你引用的内容不适用。 嗯,C++/CLI 似乎不是我想的那样。没关系我的发现。我会根据需要将所有内容交换为公共或受保护的。 请注意,您还可以与特定功能成为朋友。【参考方案2】:

如果您的想法是将整个模块彼此隔离,您可以尝试保留两组头文件——一组使用“公共”方法,另一组使用“内部”方法。我现在不确定如何避免重复; AFAIK一个类只能在编译单元中声明一次,公共和内部头都需要一个完整的类定义。一种,公认的非常笨拙的方法是让部分文件像 _Foo.public.h_Foo.internal.h 只包含方法声明,而“真正的”头文件将其中一个或两个包含在类声明主体中:

Foo.public.h

class Foo 
    #include "_foo.public.h"

Foo.internal.h

class Foo 
    #include "_foo.internal.h"

源文件会引用它们自己模块的内部头文件,但会引用它们依赖项的公共头文件。应该可以调整项目布局并构建脚本以使其合理透明。 (例如,为每个模块设置正确目录的包含路径。)

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

【讨论】:

这在标准 C++ 中是完全禁止的(参见:一个定义规则)。您可能会在某些特定环境中侥幸逃脱,但更好的范例是将公共部分作为私有(完整)实现的基类。【参考方案3】:

对于任何仍然感兴趣的人,我认为有一个宏观解决方案。通常在创建 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 中,properties->C\C++->preprocessor->preprocessor 定义),而不是使用者项目的设置。所以对于消费者来说,宏被替换为“私有”,但它在 DLL 项目中是“公共的”。您可以像使用任何其他访问修饰符一样使用它:

class DLL Foo

public:
    int public_thing;
INTERNAL:
    int internal_thing;
;

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

【讨论】:

以上是关于C++ 等价于 C# 的内部的主要内容,如果未能解决你的问题,请参考以下文章

将复杂的结构(带有结构的内部数组)从 C# 传递到 C++

C++ 等价于 Java 的链表/C# 的数组列表?

您可以在 Java 中获得的最接近 C# 内部修改的内容是啥?

C#:指向结构内部结构的指针

C# 中的 C++ 内存复制等价物

C++ DWORD 的 C# 等价物是啥?