当基类中唯一的候选构造函数标记为explicit
时,是否可以将派生类的实例隐式转换为其基类的实例?
我跑了这个:
struct Base {
Base() {}
explicit Base(Base const& b) {}
};
struct Derived : Base {};
int main() {
Derived d;
Base b = d;
}
得到了这个:
错误:没有匹配函数来调用'Base :: Base(Derived&)'
然后我跑了这个:
struct Base {
Base() {}
Base(Base const& b) {}
};
struct Derived : Base {};
int main() {
Derived d;
Base b = d;
}
没有错误。
但是我并不完全相信这个测试会因explicit
而不是ctor综合而成功。特别是,我不认为explicit
关心论证的类型,但它会强迫我写Base b = static_cast<Base>(d)
......在任何一种情况下我都不会这样做。
答案 0 :(得分:2)
转换失败并非如此。复制初始化需要一个可访问的复制构造函数。
这也失败了:
struct Base {
Base() {}
explicit Base(Base const& b) {}
};
int main() {
Base d;
Base b = d;
}
答案 1 :(得分:1)
事后看来,似乎很清楚。
这里的元素是:
Base(Base const&)
,我没有提供构造函数Base(Derived const&)
。explicit
,但我没有提供明确的转换。所以,答案是“不”。
答案 2 :(得分:-1)
此:
int main() {
Derived d;
Base b = d;
}
不是向上转播。这是创建一个名为b
的新对象,其中包含值为d
的副本。为了进行向上转换,您必须使用多态值(引用或指针)。因此,上传将是:
int main() {
Derived d;
Base &b = d;
}
变量b
包含对Base
d
部分的引用。如果Base
有一些公开成员int baseValue;
,则b.baseValue
会引用与d.baseValue
完全相同的数据。例如:
int main() {
Derived d;
Base &b = d;
d.baseValue = 10;
cout << b.baseValue << endl;
}
这将写10
。如果b
不是引用,而是常规对象,则会在d
的值更改之前从d
复制(初始化)值。因此改变一个不会改变另一个。
explicit
关键字的目的是阻止Base b = d
之类的语法工作。如果你创建一个构造函数explicit
,你会说,“我不希望编译器隐式调用这个拷贝构造函数。如果用户要使用它,那么它们必须这样说的。”如果你想隐式转换类型,那么你必须这样说。