问题标签 [friend-class]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
42 浏览

c++ - 朋友类和函数参数的范围

我正在编写一个供自己使用的反射实用程序,我简化了代码(删除复杂的模板),如下所示:

编译器抱怨iis private of class A

我现在很困惑,我知道参数的作用域是函数原型作用域,但我不太了解它与 C++ 特性朋友类的关系。

谁能帮助我应该怎么做才能将私有传递&A::ifield对象?

0 投票
1 回答
77 浏览

c++ - C++:模板可以成为类的朋友吗?

是否有可能成为一个类的朋友,一个类模板的所有可能的变体?

只是为了澄清,例如,这样的事情:

所以任何B<X>变体都可以操纵A.

A是一个小而简单的类,有很多朋友在操作它的属性。只有其中一个需要成为模板。我知道我可以这样做:

但是所以我不得不在所有其他朋友中更改我的代码,我想避免它。

0 投票
0 回答
61 浏览

c++ - 两个私有嵌套类之间的友谊

我有 4 个班级,A、A1、B 和 B1。类 A 包含一个私有嵌套类 A1,类 B 包含一个私有嵌套类 B1。我希望 B::B1 类的构造函数能够访问 A::A1 类型对象的私有数据成员。我的解决方案是使用关键字“朋友”。但是,我无法让外部班级之间的相互友谊发挥作用,并且在线指南不考虑两个私人嵌套班级之间的友谊。

计划是让 B 成为 A 的朋友,以便 B1 了解 A1。然后让 A 成为 B 的朋友,这样 A1 就知道 B1。然后让 B1 成为 A1 的朋友,这样 B1 就可以访问 A1 的私有数据成员。这是一些无法做到这一点的代码。您可以随意忽略它。

这段代码似乎有很多错误,但在我试图让它工作的所有尝试中都有很多不同类型的错误。对这些错误的解释会有所帮助,但我正在寻找一个关于如何正确建立友谊和前向声明的工作示例。

0 投票
2 回答
140 浏览

c++ - 注入的类名可以用作友元声明中的类型名吗?

考虑这段代码:

它在 gcc 和 clang 中编译,但它有效吗?[temp.local].1 说:

当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它是一个模板名称指类模板本身。

粗体部分似乎适用,朋友声明似乎需要类型名称而不是模板名称(参见 [class.friend])。

是编译器错误还是我误读了标准?

0 投票
2 回答
235 浏览

c++ - 如何允许 std::unique_ptr 访问类的私有析构函数或使用私有析构函数实现 C++ 工厂类?

我对使用 SDL、OpenGL 和 C++ 的游戏开发相当深入,并且正在寻找方法来优化游戏在 GLSL 着色器之间切换的方式,以处理不同类型的许多不同对象。这更像是一个 C++ 问题,而不是 OpenGL 问题。但是,我仍然想提供尽可能多的上下文,因为我觉得需要一些理由来说明为什么我需要的提议的 Shader 类需要按原样创建/删除。

前四个部分是我的理由,旅程和尝试导致这一点,但是我的问题很可能仅通过最后一部分来回答,我特意把它写成一个 tldr。

Shader 类的必要性:

当在游戏过程中创建游戏对象时,我已经看到许多在同一函数中创建、编译和删除 OpenGL 着色器的在线实现。事实证明,这在我的游戏的特定部分效率低下且速度太慢。因此,我需要一个在加载期间创建和编译着色器的系统,然后在游戏期间间歇性地在它们之间使用/交换,然后再被删除。

这导致了Shader管理 OpenGL 着色器的类()的创建。该类的每个实例都应管理一个唯一的 OpenGL 着色器,并包含围绕着色器类型的一些复杂行为,它从哪里加载,在哪里使用,它采用的统一变量等。

话虽如此,这个类最重要的作用是存储从 中返回的GLuint变量,并通过这个来管理所有与 OpenGL 着色器相关的 OpenGL 调用。我知道鉴于 OpenGL 的全局性质,这实际上是徒劳的(因为程序中的任何地方都可以在技术上调用匹配并破坏类),但是为了有意将所有 OpenGL 调用封装到整个代码库中非常特定的区域,这系统将大大降低代码复杂度。idglCreateShader()idglDeleteShader()id

问题从哪里开始...

管理 this 的最“自动”方式GLuint id是调用glCreateShader()对象的构造和glDeleteShader()对象的销毁。void createShader()这保证(在 OpenGL 限制内)OpenGL 着色器将存在于 C++ 着色器对象的整个生命周期中,并且无需调用某些deleteShader()函数。

这一切都很好,但是当考虑复制这个对象会发生什么时,很快就会出现问题。如果这个对象的副本被破坏了怎么办?这意味着glDeleteShader()它将被调用并有效地破坏着色器对象的所有副本。

像意外调用std::vector::push_back()着色器向量这样的简单错误呢?各种std::vector方法可以调用其类型的构造函数/复制构造函数/析构函数,这可能会导致与上述相同的问题。

好吧……即使很乱,我们也可以创建一些void createShader()和方法怎么样?deleteShader()不幸的是,这只是推迟了上述问题,因为任何修改 OpenGL 着色器的调用都会取消同步/彻底破坏具有相同id. 我在这个例子中限制了 OpenGL 调用以glCreateShader()保持glDeleteShader()简单,但是我应该注意,类中还有许多其他 OpenGL 调用会导致创建各种实例/静态变量来跟踪实例副本过于复杂证明这样做是合理的。

在进入下面的类设计之前,我想说的最后一点是,对于像原始 C++、OpenGL 和 SDL 游戏这样大的项目,如果我犯的任何潜在的 OpenGL 错误会生成编译器错误而不是图形问题,我更愿意更难追踪。这可以反映在下面的类设计中。

类的第一个版本Shader

基于以上原因,我选择了:

  • 制作构造函数private
  • 提供一个公共static create函数,该函数返回一个指向新 Shader 对象的指针来代替构造函数。
  • 制作复制构造函数private
  • 制作operator= private(尽管这可能不是必需的)。
  • 将析构函数设为私有。
  • glCreateShader()在构造函数和析构函数中调用glDeleteShader(),以使 OpenGL 着色器在该对象的生命周期中存在。
  • create函数调用new关键字(并返回指向它的指针)时,Shader::create()必须delete手动调用外部调用的地方(稍后会详细介绍)。

据我了解,前两个要点使用工厂模式,如果尝试创建类的非指针类型,则会生成编译器错误。第三、第四和第五个要点然后防止对象被复制。然后,第七个要点确保 OpenGL 着色器将在 C++ 着色器对象的相同生命周期内存在。

智能指针和主要问题:

上面我唯一不喜欢的就是new/delete调用。glDeleteShader()考虑到类试图实现的封装,它们还使对象的析构函数中的调用感觉不合适。鉴于此,我选择:

  • 更改create函数以返回类型的 astd::unique_ptrShader不是Shader指针。

然后create函数看起来像这样:

但是随后出现了一个新问题……std::make_unique不幸的是,它要求构造函数public,这会干扰上一节中描述的必需品。幸运的是,我找到了一个解决方案,将其更改为:

但是......现在std::unique_ptr要求析构函数是公开的!这……更好但不幸的是,这意味着可以在类外部手动调用析构函数,这反过来意味着glDeleteShader()可以从类外部调用该函数。

最后一课:

为简单起见,我删除了大部分实例变量、函数/构造函数参数和其他属性,但最终提议的类(大部分)如下所示:

除了析构函数是公共的这一事实之外,我对这个类中的所有内容都很满意。我已经对这个设计进行了测试,性能提升非常明显。尽管我无法想象我会不小心手动调用Shader对象的析构函数,但我不喜欢它被公开。我也觉得我可能会不小心漏掉一些东西,比如std::vector::push_back第二部分的考虑。

对于这个问题,我找到了两种可能的解决方案。我想对这些或其他解决方案提出一些建议。

  1. 使std::unique_ptr或类。std::make_unique_ 我一直在阅读诸如this one之类的线程,但是这是为了使构造函数可访问,而不是析构函数。我也不太明白制作或制作(该线程的最佳答案+评论)所需的缺点/额外考虑因素?friendShaderstd::unique_ptrstd::make_uniquefriend

  2. 根本不使用智能指针。有没有办法让我的static create()函数返回一个原始指针(使用关键字),当超出范围并调用析构函数时,它会new在类/内部自动删除?Shader

非常感谢您的宝贵时间。

0 投票
2 回答
81 浏览

c++ - 为什么编译器不喜欢与“Iter”关联的所有字符串?

我正在实现一种行为设计模式。

编译器在与“Iter”相关的行中给出错误。我完全不明白为什么会发生这种情况,更何况,如何解决?

我认为可能某处存在笔误(我正在按照书中的示例进行程序,代码是屏幕截图,需要重新输入)-但没有笔误,一切都与那里一样。

那么可能是什么问题呢?

我怀疑由于我的知识水平低,这对我来说不是很简单。

错误:

完整代码:

0 投票
1 回答
156 浏览

c++ - 访问朋友类的私有成员的朋友函数

跟随特拉维夫欧洲电视网 2019 年的捷克歌曲

众所周知,在 C++ 中,朋友的朋友不是(自动)朋友。

然而,Clang 在以下代码上与 GCC 和 MSVC 不同:

代码:https ://godbolt.org/z/rn48PTe1Y

哪一个是正确的?如果 Clang 过于宽容是错误的,那么允许访问的最佳方式是什么(除了提供公共 getter 之外?)


注意:如果友元函数只是在类中声明并在外部实现,Clang 和 GCC 都会拒绝该代码

0 投票
1 回答
50 浏览

c++ - 无法使用朋友类更改类的私有成员的值

所以我试图学习如何使用朋友类来改变私有类成员的值,但是朋友类不能改变主类的值,这是我所做的代码,我是编码世界的新手,请帮帮我:)

- 这应该打印:10 20 但正在打印:10 10

0 投票
1 回答
31 浏览

c++ - 同一命名空间中的友元类

我正在编写基于 Vulkan 的渲染器,但不幸的是出现了这个错误: 'Azazel::Instance::~Instance':无法访问在类'Azazel::Instance'中声明的私有成员 这让我很头疼。我试图在我的命名空间开始时预先声明 Azazel_Menager 类,但它不起作用,所以我改变了:

friend class Azazel_Menager;

至:

friend class Azazel::Azazel_Menager;

好吧,它也没有成功。所以在这里我请求你的帮助。也许你会看到我没有看到的东西。

Azazel_Menager:

实例.h:

参考 = std::shared_ptr