为什么友谊至少可以在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) Matthieu M.在我之前看过的这个答案中提出了一种访问保护模式,但从未有意识地考虑过一种模式:
class SomeKey {
friend class Foo;
SomeKey() {}
// possibly make it non-copyable too
};
class Bar {
public:
void protectedMethod(SomeKey);
};
Run Code Online (Sandbox Code Playgroud)
这里只有一个friend关键类可以访问protectedMethod():
class Foo {
void do_stuff(Bar& b) {
b.protectedMethod(SomeKey()); // fine, Foo is friend of SomeKey
}
};
class Baz {
void do_stuff(Bar& b) {
b.protectedMethod(SomeKey()); // error, SomeKey::SomeKey() is private
}
};
Run Code Online (Sandbox Code Playgroud)
它允许更多的细粒度访问控制不是制造Foo一个friend的Bar,避免了更复杂的代理模式.
有谁知道这种方法是否已经有一个名称,即,是一个已知的模式?
例:
template<class T>
class Base {
public:
Base();
friend class T;
};
Run Code Online (Sandbox Code Playgroud)
现在这不起作用......有没有办法做到这一点?
我实际上是想制作一个像这样的通用类封口机:
class ClassSealer {
private:
friend class Sealed;
ClassSealer() {}
};
class Sealed : private virtual ClassSealer
{
// ...
};
class FailsToDerive : public Sealed
{
// Cannot be instantiated
};
Run Code Online (Sandbox Code Playgroud)
我在这个网站上找到了这个例子,但我找不到它...(这里)
我知道还有其他方法可以做到这一点但是现在我很好奇你是否真的能做到这样的事情.
假设我有三个C++类FooA,FooB和FooC.
FooA有一个名为的成员函数Hello,我想在类FooB中调用这个函数,但我不希望类FooC能够调用它.我能想出来实现这一点的最好方法是将FooB声明为FooA的朋友类.但只要我这样做,所有 FooA的私人和受保护成员都将被曝光,这对我来说是非常不可接受的.
所以,我想知道C++(03或11)中是否有任何机制比friend类可以解决这个难题更好.
我认为如果可以使用以下语法会很好:
class FooA
{
private friend class FooB:
void Hello();
void Hello2();
private:
void Hello3();
int m_iData;
};
class FooB
{
void fun()
{
FooA objA;
objA.Hello() // right
objA.Hello2() // right
objA.Hello3() // compile error
ojbA.m_iData = 0; // compile error
}
};
class FooC
{
void fun()
{
FooA objA;
objA.Hello() // compile error
objA.Hello2() // compile error
objA.Hello3() // compile error
ojbA.m_iData = 0; // compile error
} …Run Code Online (Sandbox Code Playgroud) 显然,这种面向密钥的访问保护模式:
class SomeKey {
friend class Foo;
SomeKey() {}
// possibly non-copyable too
};
class Bar {
public:
void protectedMethod(SomeKey); // only friends of SomeKey have access
};
Run Code Online (Sandbox Code Playgroud)
......还没有一个已知的名字,因此我想找到一个好的名字,所以我们可以在不断言的情况下参考它.建议?
它应该是:
请查看以下C++ 0x lambda相关代码:
typedef uint64_t (*WEIGHT_FUNC)(void* param);
typedef std::map<std::string, WEIGHT_FUNC> CallbackTable;
CallbackTable table;
table["rand_weight"] = [](void* param) -> uint64_t
{
return (rand() % 100 + 1);
};
Run Code Online (Sandbox Code Playgroud)
我得到一个错误(在Visual Studio 2010中),lambda无法转换为类型WEIGHT_FUNC.我也知道答案:使用std::function object:
typedef std::function<uint64_t (void*)> WEIGHT_FUNC;
Run Code Online (Sandbox Code Playgroud)
但是,我也想知道如何在不使用的情况下接收lambda的类型std::function.它应该是什么类型的?
这段代码:
class B {
protected:
void Foo(){}
}
class D : public B {
public:
void Baz() {
Foo();
}
void Bar() {
printf("%x\n", &B::Foo);
}
}
Run Code Online (Sandbox Code Playgroud)
给出了这个错误:
t.cpp: In member function 'void D::Bar()':
Line 3: error: 'void B::Foo()' is protected
Run Code Online (Sandbox Code Playgroud)
顺便说一下:这看起来很相关,但是我正在寻找一个参考指标或类似内容的地方(希望这将导致如何按照我期望的方式工作).
是否可以将前向声明的类的成员函数声明为朋友?我正在尝试执行以下操作:
class BigComplicatedClass;
class Storage {
int data_;
public:
int data() { return data_; }
// OK, but provides too broad access:
friend class BigComplicatedClass;
// ERROR "invalid use of incomplete type":
friend void BigComplicatedClass::ModifyStorage();
};
Run Code Online (Sandbox Code Playgroud)
因此,目标是(i)将友元声明限制为单个方法,以及(ii)不包括复杂类的定义以减少编译时间.
一种方法可能是添加一个充当中间人的类:
// In Storage.h:
class BigComplicatedClass_Helper;
class Storage {
// (...)
friend class BigComplicatedClass_Helper;
};
// In BigComplicatedClass.h:
class BigComplicatedClass_Helper {
static int &AccessData(Storage &storage) { return storage.data_; }
friend void BigComplicatedClass::ModifyStorage();
};
Run Code Online (Sandbox Code Playgroud)
然而,这似乎有点笨拙...所以我认为必须有一个更好的解决方案!
要使用默认参数定义模板化类的朋友,是否需要在下面的代码中指定所有朋友(哪个有效)?
// Different class implementations
enum ClassImplType { CIT_CHECK, CIT_FAST, CIT_GPU, CIT_SSE, CIT_NOF_TYPES } ;
// Graph class has default template argument CIT_CHECK
template <typename T, ClassImplType impl_type = CIT_CHECK>
class graph {
//...
};
// Vertex class
template <typename T>
class vertex {
//...
friend class graph<T, CIT_CHECK>;
friend class graph<T, CIT_FAST>;
friend class graph<T, CIT_GPU>;
friend class graph<T, CIT_SSE>;
};
Run Code Online (Sandbox Code Playgroud)
我可以想象有一种更短的方式来表示为所有可能的ClassImplType枚举值定义了朋友.有点像friend class graph<T, ClassImplType>,但后者当然不起作用.
如果我使用的术语不正确,请道歉.