一个友元类使用误区(C++)
来源:互联网 发布:手机网络电话软件排名 编辑:程序博客网 时间:2024/06/06 23:51
这个问题,我困扰了好一会,决定记录一下。
一、问题引出以及分析
问题代码简化如下:
class B;class A{ friend class B;private: A() = default; bool operator()(int lhs,int rhs){ return lhs<rhs; }};class B{ //...working add_item(int times){ pq.push(times); }private: std::priority_queue<int,std::vector<int> ,A> pq;};编译出错提示信息:
'bool A::operator()(int, int)' is private
你知道问题出现在哪里吗??如果你看出来了,那么恭喜你,我是花了挺长时间纠结的。
我的理解是这样的。 类A有一个删除的默认构造函数,类的用户是没有权限新建实例的,主要是为了封装数据。我一开始以为,B是A的友元类,理论上在B的作用域中可以建立A的对象,访问A的私有接口。 这样想确实没有错误,问题出现在我是在类B的成员std::priority_queue中使用类A。 友元不具有传递性和继承性,只能在B类的作用域中可以使用,相当于在B的成员函数中使用。但是std::priority_queue中的成员不具备访问类A的权限。除非将std::priority_queue声明为类A的友元类。因此定义如下函数便报错。
add_item(int times){ pq.push(times); }因为在pq的成员中使用了类A的成员函数, 每次向pq插入一个元素便会调用这个类A这个成员,如下
bool operator()(int lhs,int rhs){ return lhs<rhs; }
二、问题解决
1、很自然会想到将类A的成员权限设置为public。 这样所有类A的用户都能访问,确实能解决问题。但是这样不能对数据很好的封装。因为类A只是一个辅助类。2、类A只是作为一个函数对象存在而已,有没有别的办法代替类A? 答案是有,使用其他函数对象(函数,函数指针,lambda表达式,重载了函数调用运算符的类),这里lambda表达式代替A, 但是这里有一个小问题。lambda是一个函数对象实例而不是一种类型(type),而std::priority_queue接收的是需要一个类型。 这需要一个转化。
template< class T, class Container = std::vector<T>, class Compare = std::less<typename Container::value_type>> class priority_queue;
可能会写出如下代码:
class B{ //...working add_item(int times){ pq.push(times); }private: auto Less = [](int& lhs,int rhs)->bool {return lhs<rhs;} std::priority_queue<int,std::vector<int> ,decltype(Less)> pq;};这也是行不通的,类在编译的时候只看声明,auto需要根据给出的lambda 表达式推断出对应的类型,因此成员Less出错,当然pq声明也就出错了。
3、接下来就开始思考如何应对这个问题。查看std::priority_queue的constructor. 自定义一个函数比较器类型。
explicit priority_queue( const Compare& compare = Compare(), const Container& cont = Container() );(until C++11)priority_queue( const Compare& compare, const Container& cont );(since C++11)//...省略
代码如下: 使用简单函数指针作为类型。新建一个对象需要提供这个函数指针类型的一个实例。
#include <iostream>#include<stdio.h>#include<queue>#include<vector>#include<functional>class B{ //...working add_item(int times){ pq.push(times); }private: std::priority_queue<int,std::vector<int> ,auto(*)(const int& ,const int&)->bool > pq{ [](const int& lhs, const int& rhs)->bool { return lhs < rhs; } };};在C++11。 可以使用标准库提供的函数类型(std::function)
class B{ //...working add_item(int times){ pq.push(times); }private: std::priority_queue<int,std::vector<int> ,std::function<bool(const int&,const int& )> > pq{ [](const int& lhs, const int& rhs)->bool { return lhs < rhs; } };};
0 0
- 一个友元类使用误区(C++)
- ACE_Message_Block的一个使用误区
- UIAlertController的一个使用误区
- C语言-unsigned使用误区
- C++Vector的使用误区
- C++Vector的使用误区
- c++Vector的使用误区
- C++Vector的使用误区
- 使用==比较的一个误区(如Integer)
- EditPlus+JDK使用中的一个误区。
- 使用 InterlockedIncrement/InterlockedDecrement 的一个误区
- Jquery TreeTable使用的一个误区
- Python中的一个误区----*的使用
- 使用 android EventBus的一个误区
- Spring事务使用的一个误区
- oracle 中使用 rownum 的一个误区
- Numpy自定义dtype的一个使用误区
- 一个误区
- Java语法学习1
- python机器学习常用语法
- Redis源码剖析--字典dict
- Python中排序常用到的sort 、sorted和argsort函数
- oracle正确卸载步骤
- 一个友元类使用误区(C++)
- 微信小程序开发例子-录音和播放声音
- Redis源码剖析--跳跃表zskiplist
- ScrollView滑动到底部继续向上滑和滑动到顶部继续向下滑
- Redis源码剖析--基数统计hyperloglog
- TypedArray 为什么需要调用recycle()
- ubuntu 12.04 安装Groovy
- 数位dp
- 【Spring】Spring高级话题-计划任务-@EnableScheduling