将构造函数标记为 __explicitly__ 需要对象类型

Posted

技术标签:

【中文标题】将构造函数标记为 __explicitly__ 需要对象类型【英文标题】:Mark constructor as __explicitly__ requiring an object type 【发布时间】:2011-12-09 02:55:43 【问题描述】:

我有一个接受Material 类型对象的构造函数:

SomeClass::SomeClass( const Material& mat ) ;

但是,Material 允许通过 Vector 进行构造:

Material::Material( const Vector& v ) ;

因此,SomeClass 可以允许由Vector 构造:

SomeClass m( vec ) ; // valid, since vec is constructed to a Material first,
// then is passed to the SomeClass(Material) ctor

但是,在使用这种类型的 ctor(在同一个项目的不同类中!)不止一次“射自己的脚”之后,我想禁止构造SomeClass 直接由 Vector 对象组成,而不是始终需要传递 Material

有没有办法做到这一点?不知何故认为它与explicit 关键字有关。

【问题讨论】:

¤ 您可以将Material::Material 构造函数标记为explicit。在 C++03 中,您还必须确保在 Vector 类中没有 operator Material。但是,使用 C++11,您还可以将这样的转换运算符标记为 explicit(最好是恕我直言,以避免转换运算符,而是通常通过命名函数提供转换)。干杯&hth., 【参考方案1】:

您声明Material(const Vector &v)explicit;这可以防止从一个到另一个的隐式转换。

这当然不是对SomeClass的具体限制;这是对任何隐式转换实例的全球禁令。

【讨论】:

【参考方案2】:

如果不影响从 Vector 透明构造 Material 的能力,您将无法做到这一点。

如果你让Material的构造函数explicit

explicit Material( const Vector& v ) ;

那么你将总是必须写Material(v) 来构造一个实例。这将防止您意外地用 Vector 实例化 SomeClass,但它也会破坏所有计算结果为 Vector 的表达式,其中应该是 Material

这是有道理的,因为通过不声明构造函数explicit,您是在说“无论上下文如何,Vector 都与Material 一样好”。然后你不能后退半步说“哦,好吧,除非在构造 SomeClass 时”。

【讨论】:

是的!这是一个很棒的功能!【参考方案3】:

制作Materialexplicit的构造函数:

explicit Material(const Vector& v)  ... 

或者,如果您不想这样做,作为一个 hack 并以const-正确性作为牺牲,请从const Material& mat 中删除const。您将无法将临时对象传递给 SomeClass 的构造函数(或 const 实例,这可能是一个太大的牺牲)。但是,这使您无法执行您可能想做的SomeClass(Material(v))。所以只能接近自己想要的,但恐怕不是完全可以的。

【讨论】:

从构造函数参数中删除const 可以达到目的,但不可取。 @OliCharlesworth 是的,这就是为什么我说这有点像 hack。我只是想让他知道所有选项,也许他不知道临时变量只能作为 const 引用传递,而不仅仅是引用。

以上是关于将构造函数标记为 __explicitly__ 需要对象类型的主要内容,如果未能解决你的问题,请参考以下文章

GCC __attribute__((constructor)) 在对象构造函数之前调用

C++02_类与对象(下)

类和对象(下)

魔法函数

第8课 列表初始化_防止类型收窄explicit关键字

python 构造函数__init__() 和 实例属性实例方法