问题标签 [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.
c++ - 朋友类和函数参数的范围
我正在编写一个供自己使用的反射实用程序,我简化了代码(删除复杂的模板),如下所示:
编译器抱怨i
is private of class A
。
我现在很困惑,我知道参数的作用域是函数原型作用域,但我不太了解它与 C++ 特性朋友类的关系。
谁能帮助我应该怎么做才能将私有传递&A::i
给field
对象?
c++ - C++:模板可以成为类的朋友吗?
是否有可能成为一个类的朋友,一个类模板的所有可能的变体?
只是为了澄清,例如,这样的事情:
所以任何B<X>
变体都可以操纵A
.
A
是一个小而简单的类,有很多朋友在操作它的属性。只有其中一个需要成为模板。我知道我可以这样做:
但是所以我不得不在所有其他朋友中更改我的代码,我想避免它。
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 的私有数据成员。这是一些无法做到这一点的代码。您可以随意忽略它。
这段代码似乎有很多错误,但在我试图让它工作的所有尝试中都有很多不同类型的错误。对这些错误的解释会有所帮助,但我正在寻找一个关于如何正确建立友谊和前向声明的工作示例。
c++ - 注入的类名可以用作友元声明中的类型名吗?
考虑这段代码:
它在 gcc 和 clang 中编译,但它有效吗?[temp.local].1 说:
当它与模板参数列表一起使用时,作为模板模板参数的模板参数,或作为朋友类模板声明的详细类型说明符中的最终标识符,它是一个模板名称指类模板本身。
粗体部分似乎适用,朋友声明似乎需要类型名称而不是模板名称(参见 [class.friend])。
是编译器错误还是我误读了标准?
c++ - 如何允许 std::unique_ptr 访问类的私有析构函数或使用私有析构函数实现 C++ 工厂类?
我对使用 SDL、OpenGL 和 C++ 的游戏开发相当深入,并且正在寻找方法来优化游戏在 GLSL 着色器之间切换的方式,以处理不同类型的许多不同对象。这更像是一个 C++ 问题,而不是 OpenGL 问题。但是,我仍然想提供尽可能多的上下文,因为我觉得需要一些理由来说明为什么我需要的提议的 Shader 类需要按原样创建/删除。
前四个部分是我的理由,旅程和尝试导致这一点,但是我的问题很可能仅通过最后一部分来回答,我特意把它写成一个 tldr。
Shader 类的必要性:
当在游戏过程中创建游戏对象时,我已经看到许多在同一函数中创建、编译和删除 OpenGL 着色器的在线实现。事实证明,这在我的游戏的特定部分效率低下且速度太慢。因此,我需要一个在加载期间创建和编译着色器的系统,然后在游戏期间间歇性地在它们之间使用/交换,然后再被删除。
这导致了Shader
管理 OpenGL 着色器的类()的创建。该类的每个实例都应管理一个唯一的 OpenGL 着色器,并包含围绕着色器类型的一些复杂行为,它从哪里加载,在哪里使用,它采用的统一变量等。
话虽如此,这个类最重要的作用是存储从 中返回的GLuint
变量,并通过这个来管理所有与 OpenGL 着色器相关的 OpenGL 调用。我知道鉴于 OpenGL 的全局性质,这实际上是徒劳的(因为程序中的任何地方都可以在技术上调用匹配并破坏类),但是为了有意将所有 OpenGL 调用封装到整个代码库中非常特定的区域,这系统将大大降低代码复杂度。id
glCreateShader()
id
glDeleteShader()
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_ptr
而Shader
不是Shader
指针。
然后create
函数看起来像这样:
但是随后出现了一个新问题……std::make_unique
不幸的是,它要求构造函数是public
,这会干扰上一节中描述的必需品。幸运的是,我找到了一个解决方案,将其更改为:
但是......现在std::unique_ptr
要求析构函数是公开的!这……更好但不幸的是,这意味着可以在类外部手动调用析构函数,这反过来意味着glDeleteShader()
可以从类外部调用该函数。
最后一课:
为简单起见,我删除了大部分实例变量、函数/构造函数参数和其他属性,但最终提议的类(大部分)如下所示:
除了析构函数是公共的这一事实之外,我对这个类中的所有内容都很满意。我已经对这个设计进行了测试,性能提升非常明显。尽管我无法想象我会不小心手动调用Shader
对象的析构函数,但我不喜欢它被公开。我也觉得我可能会不小心漏掉一些东西,比如std::vector::push_back
第二部分的考虑。
对于这个问题,我找到了两种可能的解决方案。我想对这些或其他解决方案提出一些建议。
使
std::unique_ptr
或类。std::make_unique
_ 我一直在阅读诸如this one之类的线程,但是这是为了使构造函数可访问,而不是析构函数。我也不太明白制作或制作(该线程的最佳答案+评论)所需的缺点/额外考虑因素?friend
Shader
std::unique_ptr
std::make_unique
friend
根本不使用智能指针。有没有办法让我的
static create()
函数返回一个原始指针(使用关键字),当超出范围并调用析构函数时,它会new
在类/内部自动删除?Shader
非常感谢您的宝贵时间。
c++ - 为什么编译器不喜欢与“Iter”关联的所有字符串?
我正在实现一种行为设计模式。
编译器在与“Iter”相关的行中给出错误。我完全不明白为什么会发生这种情况,更何况,如何解决?
我认为可能某处存在笔误(我正在按照书中的示例进行程序,代码是屏幕截图,需要重新输入)-但没有笔误,一切都与那里一样。
那么可能是什么问题呢?
我怀疑由于我的知识水平低,这对我来说不是很简单。
错误:
完整代码:
c++ - 访问朋友类的私有成员的朋友函数
众所周知,在 C++ 中,朋友的朋友不是(自动)朋友。
然而,Clang 在以下代码上与 GCC 和 MSVC 不同:
代码:https ://godbolt.org/z/rn48PTe1Y
哪一个是正确的?如果 Clang 过于宽容是错误的,那么允许访问的最佳方式是什么(除了提供公共 getter 之外?)
注意:如果友元函数只是在类中声明并在外部实现,Clang 和 GCC 都会拒绝该代码。
c++ - 无法使用朋友类更改类的私有成员的值
所以我试图学习如何使用朋友类来改变私有类成员的值,但是朋友类不能改变主类的值,这是我所做的代码,我是编码世界的新手,请帮帮我:)
- 这应该打印:10 20 但正在打印:10 10
c++ - 同一命名空间中的友元类
我正在编写基于 Vulkan 的渲染器,但不幸的是出现了这个错误: 'Azazel::Instance::~Instance':无法访问在类'Azazel::Instance'中声明的私有成员 这让我很头疼。我试图在我的命名空间开始时预先声明 Azazel_Menager 类,但它不起作用,所以我改变了:
friend class Azazel_Menager;
至:
friend class Azazel::Azazel_Menager;
好吧,它也没有成功。所以在这里我请求你的帮助。也许你会看到我没有看到的东西。
Azazel_Menager:
实例.h:
参考 = std::shared_ptr