“显式”对静态上行的影响

时间:2011-07-17 01:49:03

标签: c++

当基类中唯一的候选构造函数标记为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) ......在任何一种情况下我都不会这样做。

3 个答案:

答案 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,你会说,“我不希望编译器隐式调用这个拷贝构造函数。如果用户要使用它,那么它们必须这样说的。”如果你想隐式转换类型,那么你必须这样说。