我读到一个声明为成员函数的重载运算符是非对称的,因为它只能有一个参数而另一个自动传递的参数是this指针.所以没有比较它们的标准.另一方面,声明为a的重载运算符friend是对称的,因为我们传递两个相同类型的参数,因此可以对它们进行比较.
我的问题是,当我仍然可以将指针的左值与参考值进行比较时,为什么会选择朋友?(使用非对称版本提供与对称相同的结果)为什么STL算法仅使用对称版本?
c++ operator-overloading member-functions friend-function non-member-functions
当我们希望它访问该类的私有成员时,我们将非成员函数作为类的朋友.这赋予它与静态成员函数相同的访问权限.两种选择都会为您提供一个与该类的任何实例无关的函数.
什么时候必须使用朋友功能?什么时候必须使用静态函数?如果两者都是解决问题的可行方案,那么我们如何权衡它们的适用性呢?是否有一个默认情况下应该首选?
例如,当实现一个工厂创建foo只有私有构造函数的类的实例时,工厂函数应该是foo(你会调用foo::create())的静态成员还是应该是友元函数(你会调用create_foo())?
在您尝试阅读整篇文章之前,请了解:
fameta::counter类中,以解决一些剩余的怪癖。你可以在 github 上找到它;自从 Filip Roséen 在 2015 年发现/发明了通过友元注入编译时间计数器的黑魔法是在 C++ 中,我一直对这个设备有点着迷,所以当 CWG决定功能必须去时,我很失望,但仍然充满希望可以通过向他们展示一些引人注目的用例来改变他们的想法。
然后,几年前,我决定再看一遍,以便uberswitch es可以嵌套 - 在我看来,这是一个有趣的用例 - 只是发现它不再适用于新版本的可用的编译器,即使问题 2118是(现在仍然是)处于打开状态:代码会编译,但计数器不会增加。
该问题已在 Roséen 的网站和最近的 stackoverflow 上报告:Does C++ support compile-time counters?
我想了解编译器发生了什么变化,使看似仍然有效的 C++ 不再起作用。为此,我在互联网上广泛搜索,寻找有人谈论它,但无济于事。所以我开始尝试并得出了一些结论,我在这里提出这些结论是希望能从这里的知识渊博的人那里得到反馈。
为了清楚起见,我在下面展示了 Roséen 的原始代码。有关其工作原理的说明,请参阅他的网站:
template<int N>
struct flag {
friend constexpr int adl_flag …Run Code Online (Sandbox Code Playgroud) c++ counter friend-function argument-dependent-lookup constexpr
我想声明std::make_unique函数是我班级的朋友.原因是我想声明我的构造函数protected并提供一种使用创建对象的替代方法unique_ptr.这是一个示例代码:
#include <memory>
template <typename T>
class A
{
public:
// Somehow I want to declare make_unique as a friend
friend std::unique_ptr<A<T>> std::make_unique<A<T>>();
static std::unique_ptr<A> CreateA(T x)
{
//return std::unique_ptr<A>(new A(x)); // works
return std::make_unique<A>(x); // doesn't work
}
protected:
A(T x) { (void)x; }
};
int main()
{
std::unique_ptr<A<int>> a = A<int>::CreateA(5);
(void)a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在我收到此错误:
Start
In file included from prog.cc:1:
/usr/local/libcxx-head/include/c++/v1/memory:3152:32: error: calling a protected constructor of class 'A<int>'
return …Run Code Online (Sandbox Code Playgroud) 我试图重载c ++运算符==但我得到一些错误...
错误C2662:'CombatEvent :: getType':无法将'this'指针从'const CombatEvent'转换为'CombatEvent&'
这个错误就在这一行
if (lhs.getType() == rhs.getType())
Run Code Online (Sandbox Code Playgroud)
看下面的代码:
class CombatEvent {
public:
CombatEvent(void);
~CombatEvent(void);
enum CombatEventType {
AttackingType,
...
LowResourcesType
};
CombatEventType getType();
BaseAgent* getAgent();
friend bool operator<(const CombatEvent& lhs, const CombatEvent& rhs) {
if (lhs.getType() == rhs.getType())
return true;
return false;
}
friend bool operator==(const CombatEvent& lhs, const CombatEvent& rhs) {
if (lhs.getType() == rhs.getType())
return true;
return false;
}
private:
UnitType unitType;
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮忙吗?
我不明白为什么以下不能编译(例如在 gcc 9.10 或 MS VS C++ 2019 中):
class X {
public:
friend bool operator==(int, X const &);
};
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // Error: 'operator==' not defined
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但以下代码编译没有任何问题:
class X {
public:
};
bool operator==(int, X const &);
int main() {
2 == X(); // ok...
static_cast<bool (*)(int, X const &)>(&operator==); // OK!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的期望是 X 的友元函数 (operator==) 表现为独立函数 (operator==)。我缺少什么?谢谢
我想知道是否有一种方法可以使我们friend使用类在特定命名空间中定义所有函数?
特别是,我有一个班级,例如:
class C {
private:
// ...
public:
// ...
friend C* B::f1(C*);
friend C* B::f2(C*);
friend C* B::f3(C*);
friend C* B::f4(C*);
friend C* B::f5(C*);
};
Run Code Online (Sandbox Code Playgroud)
和命名空间B:
namespace B {
C* f1(C* x);
C* f2(C* x);
C* f3(C* x);
C* f4(C* x);
C* f5(C* x);
};
Run Code Online (Sandbox Code Playgroud)
现在,我宁愿避免在类定义中编写5行来使命名空间的所有五个函数B与类一起使用,C并告诉编译器命名空间B中定义的所有函数都是类的朋友C(即可以访问它的私有)成员).
我想快速修复是将命名空间更改为类并将函数定义为静态成员,然后将类声明为类B的朋友C.但是,出于好奇,我想知道命名空间是否也可以这样做?
提前致谢.
请考虑以下代码:
#include <vector>
template<typename T> class Container;
template<typename T> Container<Container<T>> make_double_container(const std::vector<std::vector<T>>&);
template<typename T>
class Container {
std::vector<T> v;
friend Container<Container<T>> make_double_container<T>(const std::vector<std::vector<T>>&);
public:
Container() {}
explicit Container(std::vector<T> v) : v(v) {}
};
template<typename T>
Container<Container<T>> make_double_container(const std::vector<std::vector<T>>& v) {
Container<Container<T>> c;
for(const auto& x : v) {
c.v.push_back(Container<T>(x));
}
return c;
}
int main() {
std::vector<std::vector<int>> v{{1,2,3},{4,5,6}};
auto c = make_double_container(v);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器告诉我:
main.cpp: In instantiation of 'Container<Container<T> > make_double_container(const std::vector<std::vector<T> >&) [with T = int]':
main.cpp:27:37: …Run Code Online (Sandbox Code Playgroud) 我怀疑与C++中的朋友函数有关.Friend函数不是claas的成员函数,可以直接从main调用.那么,如果我们将friend函数保持在private或public部分内部,它会有什么不同class.我一般都注意到这些friend功能总是在公共部分.在什么情况下我们应该保持friend功能private.
考虑以下代码:
namespace foo {}
class A
{
class B
{
};
friend int foo::bar( B& );
};
namespace foo
{
int bar( A::B& )
{
}
}
Run Code Online (Sandbox Code Playgroud)
G ++ 4.4.3告诉我:
friendfun-innerclass.cpp:21:错误:'int foo :: bar(A :: B&)'应该在'foo'中声明
但我无法宣布:
namespace foo
{
int bar( A::B& );
}
Run Code Online (Sandbox Code Playgroud)
在A类定义之前因为A :: B尚未声明.而且我不能明确声明"A类:: B",声明类BI必须给出类A的定义,据我所知,"朋友"声明必须在A类的定义中.
对我来说很奇怪的是,如果我从命名空间foo中取出函数"bar()",一切正常.对我来说似乎违反直觉的是,在命名空间内部或不在命名空间内部使用函数会改变编译器是否接受类中的友元函数声明.
有没有人知道如何通过这种方式来构建所有声明并使其发挥作用?
c++ ×10
friend-function ×10
c++14 ×2
constexpr ×1
counter ×1
friend ×1
friend-class ×1
namespaces ×1
syntax-error ×1
templates ×1
unique-ptr ×1