当前位置:网站首页>Tips for this week 134: make_ Unique and private constructors
Tips for this week 134: make_ Unique and private constructors
2022-07-07 17:57:00 【-Flying crane-】
As totw#134 Originally published in 2017 year 5 month 10 Japan
By Google engineers Yitzhak Mandelbaum A literary creation
therefore , You read the tips #126 And prepare to leave something new . Everything is normal , Until you try to use absl::make_unique And use private constructors to construct objects , But the compilation failed . Let's take a look at a specific example of this problem , In order to understand what went wrong . then , We can discuss some solutions .
Example : Manufacturing widgets
You are defining a class to display widgets . Each widget has an identifier , These identifiers are subject to certain constraints . To ensure that these constraints are always met , You will be Widget The constructor of the class is declared private , And provide factory functions for users Make, Used to generate widgets with appropriate identifiers .( Suggestions on why factory functions are better than initialization methods , See Tips #42.)
class Widget {
public:
static std::unique_ptr<Widget> Make() {
return absl::make_unique<Widget>(GenerateId());
}
private:
Widget(int id) : id_(id) {
}
static int GenerateId();
int id_;
}
When you try to compile , You will get the following error :
error: calling a private constructor of class 'Widget'
{
return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
^
note: in instantiation of function template specialization
'absl::make_unique<Widget, int>' requested here
return absl::make_unique<Widget>(GenerateId());
^
note: declared private here
Widget(int id) : id_(id) {
}
When make When the private constructor has been accessed ,absl::make_unique Unable to work ! Be careful , This problem also appears under friends . for example :Widget Friends use absl::make_unique To construct Widget There will be the same problem .
Suggest
We recommend any of the following alternatives :
- Use new and absl::WrapUnique, But please explain your choice . for example :Widget Friends use absl
// Use new Access non constructor only return absl::WrapUnique(new Widget(...));
- Consider whether constructors can be safely exposed . If so , Then expose and record it when it is suitable for direct construction .
In many cases , Marking constructors private is overdesign . In these cases , The best solution is to mark your constructors public and record their correct use . However , If your constructor needs to be private ( for instance , To ensure class invariants ), Then use new and WrapUnique.
Why can't I friend absl::make_unique?
You may want to be friends absl::make_unique, So it can access your private constructor . It's a bad idea , There are several reasons :
First , Although a comprehensive discussion of friend practice is beyond the scope of this tip , But a good rule of thumb is “ Don't be a long-distance friend ”. otherwise , You will create a friend competition statement , A statement that is not maintained by the owner . See also style guide recommendations .
secondly , Please note that , You rely on absl::make_unique Implementation details , That is, it directly calls new. If it is refactored to call indirectly new—— for example , In the structure C++14 Or later ,absl::make_unique yes std::make_unique Another name for , And the friend declaration is invalid .
Last , Through friends absl::make_unique, You allow anyone to create objects in this way , So why not declare your constructor public , Then completely avoid this problem ?
std::shared_ptr Well ?
about std::shared_ptr, It's a little different . There is no absl::WrapSahred And simulation (std::shared_ptr(new T(…))) There are two distributions involved , among std::make_shared You can use one to complete . If this difference is important , Then consider idioms : Let the constructor take special tags that only specific code can create . for example :
class Widget {
class Token {
private:
Token() {
}
friend Widget;
};
public:
static std::shared_ptr<Widget> Make() {
return std::make_shared<Widget>(Token{
}, GenerateId());
}
Widget(Token, int id) : id_(id) {
}
private:
static int GenerateId();
int id_;
};
About idioms , Refer to the following article :
More Useful Empty Classes
Passkey Idiom and Better Friendship in C++
边栏推荐
- Pytorch中自制数据集进行Dataset重写
- 【网络攻防原理与技术】第3章:网络侦察技术
- 面试官:页面很卡的原因分析及解决方案?【测试面试题分享】
- zdog. JS rocket turn animation JS special effects
- 请将磁盘插入“U盘(H)“的情况&无法访问 磁盘结构损坏且无法读取
- 如何在软件研发阶段落地安全实践
- Explain it in simple terms. CNN convolutional neural network
- Ansible 学习总结(9)—— Ansible 循环、条件判断、触发器、处理失败等任务控制使用总结
- Cf:c. factors and powers of two [DP + sort + Select Board + select several numbers equal to the minimum number of known sums]
- 使用OneDNS完美解决办公网络优化问题
猜你喜欢
漫画 | 宇宙第一 IDE 到底是谁?
简单的loading动画
自动化测试:Robot FrameWork框架大家都想知道的实用技巧
物联网OTA技术介绍
toast会在程序界面上显示一个简单的提示信息
Face recognition attendance system based on Baidu flying plasma platform (easydl)
Import requirements in batches during Yolo training Txt
serachview的功能和用法
【可信计算】第十三次课:TPM扩展授权与密钥管理
zdog. JS rocket turn animation JS special effects
随机推荐
做软件测试 掌握哪些技术才能算作 “ 测试高手 ”?
2021-06-28
Function and usage of numberpick
开发一个小程序商城需要多少钱?
Define menus using XML resource files
第3章业务功能开发(用户访问项目)
JS pull down the curtain JS special effect display layer
深入浅出图解CNN-卷积神经网络
[re understand the communication model] the application of reactor mode in redis and Kafka
使用Stace排除故障的5种简单方法
Mysql 索引命中级别分析
仿今日头条APP顶部点击可居中导航
Actionbar navigation bar learning
YARN Capacity Scheduler容量调度器(超详细解读)
[OKR target management] case analysis
机器视觉(1)——概述
How to implement safety practice in software development stage
自动化测试:Robot FrameWork框架大家都想知道的实用技巧
zdog. JS rocket turn animation JS special effects
Introduction to OTA technology of Internet of things