为啥我不能将类构造函数参数设置为默认值?
Posted
技术标签:
【中文标题】为啥我不能将类构造函数参数设置为默认值?【英文标题】:Why can't I set class constructor parameter to a default value?为什么我不能将类构造函数参数设置为默认值? 【发布时间】:2016-04-23 14:20:07 【问题描述】:template<class KeyType, class ValueType, class Hash = std::hash<KeyType> >
class HashMap
public:
Hash hasher;
HashMap(Hash override_ = hasher)
hasher = override_;
;
这是我的代码。我期望发生的是,如果构造函数没有提供任何值,我将保留hasher
的默认值,否则将其更改为新值。我得到的是:invalid use of non-static data member 'hasher'
。我已经想到我可以将hasher
替换为Hash()
作为默认值;但是如果我不需要默认的Hash
对象而是更复杂的东西怎么办?为什么我的第一次尝试没有编译?
【问题讨论】:
构造函数的默认参数在对象构造开始之前被解析,所以hasher
在那个时候不会存在
一个好的解决方案是 2 个构造函数,另一个是 HashMap()
【参考方案1】:
您正在尝试将类的成员用作构造函数参数的默认值,而对象尚未创建。除非成员是静态的,否则这是行不通的。为了做你想做的事,你可以定义2个构造函数,这样:
#include <map>
template<class KeyType, class ValueType, class Hash = std::hash<KeyType> >
class HashMap
public:
Hash hasher;
HashMap(Hash override_)
hasher = override_;
HashMap()
;
【讨论】:
我不明白的是为什么我不能这样使用它。我已经通过使用Hash()
作为默认值绕过了这个问题,所以我的问题更多是关于“为什么?”而不是“如何?”。
@Akiiino hasher
此时还没有创建,要怎么使用呢?
@Slava 但是如果它是static
--- 当我第一次创建HashMap
时,它还没有创建,或者是吗?
@Akiiino:如果成员是静态的,则在程序初始化时创建,不需要实例;在对象实例化时创建一个非静态成员。
@shrike 你确定是这样吗?由于我的类具有模板参数,并且具有不同模板参数的不同实例不共享它们的static
s,因此似乎不太可能为每种可能的参数组合生成static
变量。【参考方案2】:
按照标准是禁止的。这在 C++03 标准的第 8.3.6 节中有详细说明。它基本上相当于任何不依赖于本地范围内任何内容的表达式,因此任何依赖于局部变量、函数参数或“this”的表达式都被排除在外。
【讨论】:
【参考方案3】:好吧,你可以这样做:
template<class KeyType, class ValueType, class Hash = std::hash<KeyType> >
class HashMap
public:
Hash hasher;
HashMap(Hash override_ = ) : hasherstd::move(override_)
;
如果没有提供,则调用默认构造函数。
就个人而言,我认为最好的选择是添加一个默认构造函数:
template<class KeyType, class ValueType, class Hash = std::hash<KeyType> >
class HashMap
public:
Hash hasher;
HashMap() = default;
HashMap(Hash override_) : hasherstd::move(override_)
;
【讨论】:
以上是关于为啥我不能将类构造函数参数设置为默认值?的主要内容,如果未能解决你的问题,请参考以下文章