为什么友谊至少可以在C++中继承?由于显而易见的原因,我认为传递性和反身性是被禁止的(我说这只是为了避开简单的常见问题解答引用答案),但缺乏一些令virtual friend class Foo;我困惑的东西.有谁知道这个决定背后的历史背景?友谊真的只是一个有限的黑客,从那以后,它已经进入一些不起眼的可敬用途吗?
编辑澄清:我说的是以下场景,而不是 A的孩子接触B或B及其子女的情况.我还可以想象可以选择授予访问朋友功能等的覆盖的权限.
class A {
int x;
friend class B;
};
class B {
// OK as per friend declaration above.
void foo(A& a, int n) { a.x = n; }
};
class D : public B { /* can't get in A w/o 'friend class D' declaration. */ };
Run Code Online (Sandbox Code Playgroud)
接受的答案:正如Loki所说,通过在受限制的基类中创建受保护的代理函数,可以或多或少地模拟效果,因此不需要向类或虚方法层次结构授予友谊.我不喜欢需要样板代理(有条件的基础有效地成为),但我认为这被认为比大多数时候更容易被滥用的语言机制更可取.我想这可能是我购买和阅读Stroupstrup的C++的设计和演变的时候了,我已经看到这里有足够多的人推荐,以便更好地洞察这些类型的问题......
为什么C++有public成员,任何人都可以调用和friend声明所有 private成员公开给定的外部类或方法,但没有提供语法将特定成员暴露给给定的调用者?
我想表达一些例程的接口,这些例程只能由已知的调用者调用,而不必让那些调用者完全访问所有的私有,这感觉是一个合理的想法.我能想出的最好的(下面)和其他人的建议到目前为止围绕着成语/不同间接性的模式,我真的只想要一种方法来获得单一的,简单的类定义,明确指出哪些来电者(比我更细粒度),我的孩子,或绝对任何人)可以访问哪些成员.表达以下概念的最佳方式是什么?
// Can I grant Y::usesX(...) selective X::restricted(...) access more cleanly?
void Y::usesX(int n, X *x, int m) {
X::AttorneyY::restricted(*x, n);
}
struct X {
class AttorneyY; // Proxies restricted state to part or all of Y.
private:
void restricted(int); // Something preferably selectively available.
friend class AttorneyY; // Give trusted member class private access.
int personal_; // Truly private state ... …Run Code Online (Sandbox Code Playgroud) 为什么C++标准库流使用open()/ close()语义与对象生命周期分离?关闭破坏可能仍然在技术上使类RAII,但获取/释放独立性在范围中留下漏洞,其中句柄可以指向什么,但仍然需要运行时检查来捕获.
为什么图书馆设计师选择他们的方法而不是只在构造失败的构造函数中打开?
void foo() {
std::ofstream ofs;
ofs << "Can't do this!\n"; // XXX
ofs.open("foo.txt");
// Safe access requires explicit checking after open().
if (ofs) {
// Other calls still need checks but must be shielded by an initial one.
}
ofs.close();
ofs << "Whoops!\n"; // XXX
}
// This approach would seem better IMO:
void bar() {
std_raii::ofstream ofs("foo.txt"); // throw on failure and catch wherever
// do whatever, then close ofs on destruction ... …Run Code Online (Sandbox Code Playgroud) 在直观的层面上,有意义的是,需要不携带状态(通过引用或其他方式)的lambda应该可以干净地转换为裸函数指针.但是,我最近惊讶地看到GCC,Clang和MSVC中的以下失败:
int main(int, char *[]) {
void (*fp)() = []{}; // OK
//fp = [=]{}; // XXX - no user defined conversion operator available
//fp = [&]{}; // XXX - same ...
}
Run Code Online (Sandbox Code Playgroud)
C++ 17规范(或至少可见的公共草案版本N4713)在第8.4.5.1节[expr.prim.lambda.closure]的第7项中引用了带有和不带捕获的lambda:
没有lambda-capture的非泛型lambda表达式的闭包类型,其约束(如果有的话)被满足有一个转换函数指向函数,C++语言链接(10.5)具有与闭包类型相同的参数和返回类型函数调用运算符....
但是,查看正式语法,您可以在§8.4.5[expr.prim.lambda]中看到以下内容:
- lambda表达式:
- lambda-introducer复合语句
- ...
- lambda介绍人:
- [ lambda-capture opt ]
- ...
在§8.4.5.2 [expr.prim.lambda.capture]中:
- lambda-capture:
- 捕获的默认
- 捕捉列表
- capture-default,capture-list
- capture-default:
- &
- =
因此,所有编制者实际上都遵守了法律条文令我沮丧......
为什么语言将声明的存在定义为声明中的狭义语法区别,而不是基于主体是否包含对任何非静态/捕获状态的引用?
编辑:我知道方法1本质上是无效的,可能会使用方法2,但我正在寻找最好的黑客或更好的解决方案来缓解猖獗的,可变的命名空间扩散.
我在一个名称空间中有多个具有不同依赖关系的类或方法定义,并且希望尽可能使用最少的命名空间块或显式scopings,但是将#include指令与尽可能最好的需要的定义分组.我从来没有看到任何迹象表明可以告诉任何预处理器从#include内容中排除命名空间{}作用域,但我在这里询问是否有类似的东西是可能的:(见底部解释为什么我想要死的东西简单)
// NOTE: apple.h, etc., contents are *NOT* intended to be in namespace Foo!
// would prefer something most this:
#pragma magic_namespace_backout(1) // FIXME: use actually existing directive
namespace Foo {
#include "apple.h"
B *A::blah(B const *x) { /* ... */ }
#include "banana.h"
int B::whatever(C const &var) { /* ... */ }
#include "blueberry.h"
void B::something() { /* ... */ }
} // namespace Foo
Run Code Online (Sandbox Code Playgroud)
...
// over this:
#include "apple.h"
#include "banana.h"
#include "blueberry.h"
namespace Foo { …Run Code Online (Sandbox Code Playgroud) gcc是否对静态成员初始化时间有任何保证,特别是关于模板类?
我想知道在多个编译单元实例化类PWrap_T<T>::p_s之前main(),是否可以保证静态成员()将被初始化.在main的开头尝试手动触摸每个编译单元的符号是不切实际的,但我不清楚其他任何东西是否有效.
我已经用bar()不同单位的方法进行了测试,并且总是得到了预期的结果,但是我需要知道什么时候/如果gcc会将地毯拉出来以及它是否可以预防.
此外,在库完成加载之前,是否会初始化DSO中的所有静态成员?
#include <iostream>
#include <deque>
struct P;
inline std::deque<P *> &ps() { static std::deque<P *> d; return d; }
void dump();
struct P {
P(int id, char const *i) : id_(id), inf_(i) { ps().push_back(this); }
void doStuff() { std::cout << id_ << " (" << inf_ << ")" << std::endl; }
int const id_;
char const *const inf_;
};
template <class T>
struct PWrap_T { static P p_s; }; …Run Code Online (Sandbox Code Playgroud) 什么时候在Linux 2.6内核和NFSv3中确实open("fname", O_CREAT|O_EXCL)有效?当前的规范open(2)系统调用文档(http://www.kernel.org/doc/man-pages/online/pages/man2/open.2.html)说一切都很好:
- O_EXCL
- ...
On NFS, O_EXCL is only supported when using NFSv3 or later on kernel
2.6 or later. In NFS environments where O_EXCL support is not
provided, programs that rely on it for performing locking tasks will
contain a race condition. Portable programs that want to perform
atomic file locking using a lockfile, and need to avoid reliance on NFS
support for O_EXCL, can ...
Run Code Online (Sandbox Code Playgroud)
这看起来好像所有2.6内核都没问题,但是手册页面更改日志(ca late …
如何从Perl正则表达式字符串中的任意嵌套子组中删除捕获?我想将任何正则表达式嵌入到一个包络表达式中,该表达式将子正则表达式捕获为整个实体以及静态已知的后续组.我是否需要手动将正则表达式字符串转换为使用所有非捕获(?:)组(并希望我不会搞砸),或者是否有提供此功能的Perl正则表达式或库机制?
# How do I 'flatten' $regex to protect $2 and $3?
# Searching 'ABCfooDE' for 'foo' OK, but '((B|(C))fo(o)?(?:D|d)?)', etc., breaks.
# I.E., how would I turn it effectively into '(?:(?:B|(?:C))fo(?:o)?(?:D|d)?)'?
sub check {
my($line, $regex) = @_;
if ($line =~ /(^.*)($regex)(.*$)/) {
print "<", $1, "><", $2, "><", $3, ">\n";
}
}
Run Code Online (Sandbox Code Playgroud)
附录:我隐约知道的$&,$`以及$'与已被告知,如果可能避免他们,我没有访问${^PREMATCH},${^MATCH}并${^POSTMATCH}在我的Perl 5.8环境.上面的例子可以使用这些方法划分为2/3块,更复杂的实例可以手动迭代这个,但我想如果可能的话我想要一个通用的解决方案.
接受的答案:我希望存在并且令人惊讶(至少对我来说)不是,是一个封装组,使其内容不透明,以便随后的位置反向引用将内容视为单个实体,并且名称引用被取消范围. 对于Perl 5.10+,gbacon有一个潜在有用的解决方法,FM显示了在特定情况下可以实现相同效果的任何版本的手动迭代机制,但j_random_hacker …
访问者模式是在C++中完成方法参数类型识别(在参数上有效单一调度,而不是成员的类)的最快方法吗?我可能知道我要来调用尚未知亚型的元素的确切方法(S),所以不可避免地使更多的虚拟方法调用就像V::visit(A *)在A::accept(V &v) { v.visit(this); }是不可取的.
// Is the Visitor pattern recommended here? (E inherits D inherits B.)
class Foo {
public:
virtual void visit(B *) { result = 3; }
virtual void visit(D *) { result = 4; }
virtual void visit(E *) { result = 5; }
private:
int result;
}; // class Foo
// Need to add generic interface to B and its children ...
class B {
public:
virtual void accept(class Foo …Run Code Online (Sandbox Code Playgroud) 如果我有子串 S 0 , S 1 , ... S n与计算的 CRCs C 0 , C 1 , ... C n,我是否能够确定连接输入 S 0 S 1的 CRC C 0...n ...S n比线性处理整个字符串的效率要高得多?
显然, C 0...n = CRC(S 1...n,用 C 0初始化),但我想知道 C 0...n = f(C 0 ,C 1 ,... C n ) 用于某些具有 O(n) 复杂度的 f() 而不是 O(|S 0 S 1 ...S n |)。
什么是可接受的术语(如果有的话),用于描述只能虚拟调用的方法以及基础中的其他方法?我偶尔会看到这被称为回调,但这似乎偏离了该术语的原始定义.我甚至不确定这是一种被称为模式的优点,但我正试图在评论我的代码时变得更加精确.谢谢您的帮助!
// Abstract class.
class A {
public:
void run() { while (call()) { /* ... */ } }
private:
virtual bool call() = 0;
};
// Completion/specialization of A.
class B : public A {
private:
// Standard term to indicate this pattern?
bool call();
};
Run Code Online (Sandbox Code Playgroud)
摘要:这似乎被称为非虚拟接口模式,这是模板方法模式的一个特例.感谢Nick和Steven的帮助!
virtual design-patterns private non-virtual-interface template-method-pattern
可以从匹配的函数typedef中干净地创建函数指针typedef吗?
// Can I define fx_pt in terms of fx_t without duplicating the signature?
// Does decltype allow for any new sort of trick here?
using fx_t = char(int, char, std::vector<float> const &);
using fxp_t = char(*)(int, char, std::vector<float> const &);
// Using function typedef to enforce interface for declarations and definitions.
fx_t foo, bar, baz;
char foo(int) { /* ... */ }
// Using fp typedef elsewhere as normal.
fxp_t whatever{bar};
whatever(99);
Run Code Online (Sandbox Code Playgroud)
我不希望任何关于函数(指针)typedef语法的内容对我来说完全直观,但我无法确定是否可以删除重复代码.
这可能与更大的类/原始typedef和类/原始指针typedef之间的转换有关,我记得听说它们之间没有可转换的...