在C++朋友关键字允许class A
指定class B
作为其朋友.这允许Class B
访问private
/的protected
成员class A
.
我从来没有读过任何关于为什么这个被排除在C#(和VB.NET)之外的东西.早期StackOverflow问题的大多数答案似乎都说它是C++的一个有用部分,并且有充分的理由使用它.根据我的经验,我必须同意.
在我看来,另一个问题是如何friend
在C#应用程序中执行类似的操作.虽然答案通常围绕嵌套类,但它看起来并不像使用friend
关键字那么优雅.
最初的设计模式书在其示例中定期使用它.
总而言之,为什么friend
缺少C#,以及在C#中模拟它的"最佳实践"方式(或方法)是什么?
(顺便说一句,该internal
关键字不一样的东西,它可以让所有的整个组件来访问内部的阶级internal
的成员,同时friend
允许你给某一类的完全访问权限,以正好一个其他类)
我希望能够在一个包中编写一个Java类,它可以访问另一个包中的类的非公共方法,而不必使它成为另一个类的子类.这可能吗?
在复制和交换习语的漂亮答案中,有一段代码我需要一些帮助:
class dumb_array
{
public:
// ...
friend void swap(dumb_array& first, dumb_array& second) // nothrow
{
using std::swap;
swap(first.mSize, second.mSize);
swap(first.mArray, second.mArray);
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
他补充说明
还有其他声称我们应该专门为我们的类型使用std :: swap,提供一个类内交换以及一个自由函数交换等等.但这都是不必要的:任何正确使用swap都将通过一个不合格的调用,我们的功能将通过ADL找到.一个功能就可以了.
随着friend
我对"不友好"的条款一点,我必须承认.所以,我的主要问题是:
swap
静态的?它显然不使用任何成员变量.friend
进来?副题:
swap
s的noexcept
?friend iter begin()
和friend iter end()
在类中以同样的方式?我觉得friend
这里不需要,对吗?有人告诉我,在班级的公共或私人领域宣布朋友课程之间存在差异,但我似乎无法在网上找到任何关于此问题的内容,而且我不确定他们是否知道他们在谈论什么.
我的意思是区别:
class A
{
public:
friend class B;
};
Run Code Online (Sandbox Code Playgroud)
和
class A
{
private: //or nothing as the default is private
friend class B;
};
Run Code Online (Sandbox Code Playgroud)
有区别吗?
为什么友谊至少可以在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++中定义一个内部类,它是否自动成为包含它的类的朋友?例如,这是合法的:
class Outer {
public:
class Inner {
public:
void mutateOuter(Outer& o);
};
private:
int value;
};
void Outer::Inner::mutateOuter(Outer& o) {
o.value ++; // Legal? Or not?
}
Run Code Online (Sandbox Code Playgroud)
我问,因为在我试过的一些编译器(VS2003)上,这段代码不起作用,但我至少听说过它在某些编译器上有效.我无法在C++规范中找到关于此的相关部分,如果有人能够引用某些特定内容,那就是说它是合法的还是不合法的.
我现在已经在StackOverflow.com上阅读了几个关于我的问题的问题,但似乎没有一个能解决我的问题.或者我可能做错了... <<
如果我将其转换为内联函数,则重载会起作用.但是我如何让它在我的情况下工作?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)' collect2: ld returned 1 exit status
代码:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT> …
Run Code Online (Sandbox Code Playgroud) 我想做以下事情:
template <typename T>
struct foo
{
template <typename S>
friend struct foo<S>;
private:
// ...
};
Run Code Online (Sandbox Code Playgroud)
但我的编译器(VC8)扼杀了它:
error C3857: 'foo<T>': multiple template parameter lists are not allowed
Run Code Online (Sandbox Code Playgroud)
我想有所有可能的实例template struct foo
朋友foo<T>
所有T
.
我该如何工作?
编辑:这个
template <typename T>
struct foo
{
template <typename>
friend struct foo;
private:
// ...
};
Run Code Online (Sandbox Code Playgroud)
似乎编译,但它是否正确?朋友和模板的语法非常不自然.
在C++中,我经常将单元测试类作为我正在测试的类的朋友.我这样做是因为我有时觉得需要为私有方法编写单元测试,或者我想要访问某个私有成员,这样我就可以更轻松地设置对象的状态,以便我可以测试它.对我来说,这有助于保持封装和抽象,因为我没有修改类的公共接口或受保护的接口.
如果我购买第三方库,我不希望它的公共接口被一堆我不需要知道的公共方法污染,因为供应商想要进行单元测试!
我也不想担心一群受保护的成员,如果我从一个类继承,我不需要知道.
这就是我说它保留抽象和封装的原因.
在我的新工作中,他们不赞成使用朋友课,甚至进行单元测试.他们说因为班级不应该"知道"关于测试的任何内容,而且你不希望课程和测试的紧密耦合.
有人可以向我解释这些理由,以便我可以更好地理解吗?我只是不明白为什么使用朋友进行单元测试很糟糕.
c++ ×10
friend ×10
oop ×3
templates ×2
accessor ×1
c# ×1
c++11 ×1
inheritance ×1
java ×1
nested-class ×1
ostream ×1
private ×1
public ×1
unit-testing ×1