- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
有人可以描述作者 John Lakos 在以下引用中提到的精确编码策略吗?
约翰·拉科斯:
More controversially, it is often better to have two copies of a struct—e.g., one nested/private in the .h file (accessible to inline methods and friends) and the other at file scope in the .cpp file (accessible to file-scope static functions) —and make sure to keep them in sync locally than to pollute the global space with an implementation detail.
引用出现在较新的 Lakos 大部头,Large Scale C++ .
(这本书是对与 Lakos 早期著作相同主题的更新处理,Large Scale C++ Software Design)
引用在第 9 页的第 0.2 节中。
如果后面的章节清楚 Lakos 描述的内容,我会返回这里并发布答案。
与此同时,我对理解这句话着迷了,我试图浏览本书的目录和索引以寻找更多线索,但尚未找到答案。
下面是我自己的示例代码,我想象会用神秘的策略解决这个问题:
// THE HEADER
namespace project
{
class OuterComponent
{
public:
inline int GetFoo()
{
return m_inner.foo;
}
int GetBar();
private:
struct InnerComponent
{
int foo = 0;
int bar = 0;
};
InnerComponent m_inner;
};
} // namespace project
连同:
// THE CPP IMPLEMENTATION FILE
namespace project
{
namespace
{
/*
MYSTERY:
Per the book quotation, I can somehow add a "copy of InnerComponent" here?
And "make sure to keep them in sync locally"?
*/
// COMPILATION ERROR (see below)
int FileScopeComputation( OuterComponent::InnerComponent i )
{
return i.bar - 3;
}
} // namespace
int OuterComponent::GetBar()
{
return FileScopeComputation( m_inner );
}
} // namespace project
当然,上面的不会编译。
错误将类似于:
error: ‘struct project::OuterComponent::InnerComponent’ is private within this context
int FileScopeComputation( OuterComponent::InnerComponent i )
^~~~~~~~~~~~~~
名为 FileScopeComputation
的自由函数无法访问 InnerComponent
,原因我很清楚。
将上述代码与书名联系起来
回到 Lakos 的引述,我的想法是 FileScopeComputation
是引述所称的 “文件范围静态函数” 的一个实例。
使代码编译的一个“明显”解决方案是移动 InnerComponent
,以便它在 OuterComponent
的 public
部分中声明。
但是,我认为我的“显而易见”的解决方案是有罪的(根据引文)[污染] 了实现细节的全局空间。”
因此,我的代码似乎同时包含了:(a) 所提及策略的目标和 (b) 一种潜在解决方案的不必要污染。那么替代解决方案是什么?
请回答其中一个或两个:
(1) 有没有办法在 cpp 文件中制作另一个 struct InnerComponent
的拷贝,这样字段 OuterComponent::m_inner
保持私有(private),类型 OuterComponent::InnerComponent
也保持私有(private),然而函数 FileScopeComputation
有某种方式做一些“等同于”访问 InnerComponent
实例上的数据?
我尝试过一些奇怪的选角方法,但没有什么看起来值得在书中推荐的。同时,根据我的经验,Lakos在书上推荐的东西,都是非常值得推荐的。
(2) 我是否完全误读了引用适用于哪种场景?如果是这样,那么引用实际上指的是什么 C++ 软件设计问题?还有什么其他问题涉及“结构的两个拷贝...一个在 h 文件中...另一个在 cpp 文件中”?
更新:
基于perceptive answer by dfri ,上面的代码确实可以通过最小的更改进行编译,这样:
OuterComponent::m_inner
字段保持私有(private)OuterComponent::InnerComponent
类型也保持私有(private)FileScopeComputation
函数有一些方法可以访问 InnerComponent
实例上的数据头代码多了一行代码:
...
private:
struct InnerUtil; // <-- this line was ADDED. all else is same as above.
struct InnerComponent
{
int foo = 0;
int bar = 0;
};
InnerComponent m_inner;
};
cpp文件代码变为:
struct OuterComponent::InnerUtil
{
static int FileScopeComputation( OuterComponent::InnerComponent i )
{
return i.bar - 3;
}
};
int OuterComponent::GetBar()
{
return InnerUtil::FileScopeComputation( m_inner );
}
最佳答案
有可能 Lakos 实际上指的是公共(public) API 委托(delegate)调用的单独命名的类型。引用和拉科斯之间有一种相似的感觉Factoring pattern (“Imp 和 ImpUtil 模式”),尤其是“ImpUtil”部分。
struct A {};
struct B {};
struct C {};
// widgetutil.h
// (definitions placed in widgetutil.cpp)
struct WidgetUtil {
// "Keep API in sync with Widget::foo".
static void foo(const A& b, const B& c, const C& a) {
// All implementation here in the util.
(void)a; (void)b; (void)c;
}
// "Keep API in sync with Widget::bar".
static void bar(const B& b, const C& c) {
// All implementation here in the util.
(void)b; (void)c;
}
};
// widget.h
// includes "widgetutil.h"
// Public-facing API
// (Ignoring the Imp pattern, only using the Util pattern).
struct Widget {
void foo(const A& a, const B& b) const {
// Only delegation to the util.
WidgetUtil::foo(a, b, c_);
}
void bar(const B& b) const {
// Only delegation to the util.
WidgetUtil::bar(b, c_);
}
private:
C c_{};
};
int main() {
const Widget w;
w.foo(A{}, B{}); // --> WidgetUtil::foo
}
这是一种将实现细节 ( WidgetUtil
) 与面向公众的 API ( Widget
) 分开的方法,同时也有助于测试:
WidgetUtil
的单元测试中对实现细节进行了单独单元测试,Widget
可以执行而无需担心 WidgetUtil
中的副作用成员,因为后者可以在 Widget
中使用静态依赖注入(inject)完全模拟(使其成为类模板)。如果我们回顾 Lakos 的引述(在 OP 中),WidgetUtil
也可以作为文件范围类放置在 widget.cpp
中源文件,隐藏在公共(public) API 之外。这将意味着更多的封装,但不会促进与上述分离相同的测试。
最后,注意制作Widget
类模板并不一定意味着污染 widget.h
的用户的翻译单元带有定义(需要在每个 TU 中编译,包括和实例化 Widget
)。作为Widget
被制作成一个类模板仅以方便测试,它的产品实现将永远只使用一个实例,即注入(inject)产品WidgetUtil
.这意味着可以将 Widget
的定义分开类模板成员函数的声明,就像非模板类一样,并显式实例化 Widget<WidgetUtil>
特化widget.cpp
.例如。使用以下方法:
Widget
来自类模板的头文件定义,到一个单独的-timpl.h
头文件,-timpl.h
头文件又包含在关联的 .cpp
中文件,该文件又包含 Widget
的显式实例化生产中使用的单一类型模板参数的类模板,即 WidgetUtil
.测试可以类似地包括 -timpl.h
header 并实例化 Widget
改为使用模拟的 util 类的类模板。
关于c++ - 给定一个 C++ 嵌套私有(private)结构类型,是否有从文件范围静态函数访问它的策略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62616360/
如果需要在类外访问静态(例如单例),可以选择公共(public)静态而不是私有(private)静态,而当不需要公开函数时首选私有(private)静态(否则未命名的命名空间就可以了)——在这种情况下
在互联网上进行了一些搜索,但找不到简单的答案。我的问题集是在 Android 框架中使用 Java,但我相信这也是标准的 Java 行为。我理解 final 和 private 的定义,它们都用于变量
我有这个代码: public final class Board { private final int[][] blocks; private final int N; pr
对我来说,过去作为 Objective-C 开发人员很简单。一个类需要公开的每个字段都是一个属性,每个私有(private)字段都是一个没有 getter 或 setter 的实例变量。但我经常看到人
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我有一个在 Docker 容器中运行的应用程序。它需要来自公司私有(private) NPM 注册表(Sinopia)的一些私有(private)模块,并且访问这些需要用户身份验证。 Dockerfi
我试图理解 C# 使用 getters 和 setters 自动声明变量与 java 声明之间的区别。 在java中我通常这样做: private int test; public int getTe
我在 Azure 中创建了 VNET。我放入了一个子集 Azure Private Link,它在 VNET 之外和另一台虚拟机中调用 Azure Function。 当我尝试通过专用 IP 调用专用
我在 Azure 中创建了 VNET。我放入了一个子集 Azure Private Link,它在 VNET 之外和另一台虚拟机中调用 Azure Function。 当我尝试通过专用 IP 调用专用
我目前正在使用 Objective-C(适用于 iPhone)构建游戏。 为此,出于性能/复杂性原因,我略微打破了 MVC,并为 View (渲染器)提供了对模型的直接引用。这是因为它应该以 60fp
我已经在 ubuntu 上成功配置了 2 个虚拟主机站点(基于名称的虚拟主机)。我的 apache 版本是 2.2.22。 这两个站点都在本地主机上工作。 /etc/hosts 条目 127.0.0.
考虑下面的类 public class A { private final Map cache; public HeavyObject getThing(); } 假设不能泄漏对缓存
我有一个类,它有一个方法,我希望它只能被它的子对象访问,而不能被这个包中的其他类访问。 Modifier | Class | Package | Subclass | World ———————
本文实例讲述了JavaScript中的公有、私有、特权和静态成员用法。分享给大家供大家参考。具体分析如下: 下面的内容是在《JavaScript.DOM高级程序设计》里面摘抄出来的,比较容易理解,
我有一个用例,我已将其简化为以下程序: public class A { private int x = 100; class B { private int y = ne
问题: 类声明如下: class Select { public: template static Iterator function(Iterator , Iterator , bo
我是一名初级 PHP 程序员。我还有很多东西要学。这就是我问这个问题的原因。在一个类中,您有一个公共(public)函数,您可以从该类外部调用它。有时你有一个私有(private)函数,你可以在私有(
问题是: 何时使用私有(private)函数,何时使用嵌套函数? (我在问 F# 但也许答案可能与其他功能语言相关) 一个小例子 namespace SomeName module BinaryRea
我发现工作表中仍然可以使用私有(private)函数。它们是隐藏的,但如果用户输入他们的名字,他们就会被调用。为什么?它应该以这种方式工作吗?有没有办法完全阻止用户定义的函数在 VBA 项目之外使用?
所以我最近开始尝试使用 Kotlin,我偶然发现了这个: If a top-level declaration is marked private, it is private to the pack
我是一名优秀的程序员,十分优秀!