class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
func 会接受两个选项:基础和派生吗?
class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
func 会接受两个选项:基础和派生吗?
不,这行不通。func
接受对 的左值引用boost::optional<Base>
。这意味着它可以接受 typeboost::optional<Base>
的左值、公开且明确地派生自 的类型的左值boost::optional<Base>
,或具有operator boost::optional<Base>&()
. 这些都不是真的boost::optional<Derived>
。类模板在 C++ 类型系统中不是协变的 -boost::optional<Derived>
不继承自boost::optional<Base>
.
如果func
按价值论点,那将是一个不同的故事。如果它看起来像:
void func(boost::optional<Base> ) { }
在这种情况下,您可以使用. 但是那个转换构造函数被标记了,所以你必须写:func
boost::optional<Derived>
explicit
func(boost::optional<Base>{x});
这是明确的,这很好——你清楚地表明你正在(可能)切片x
。
即使它会起作用(这可能是我没有检查过的),它也会导致切片。只有Base
部分存储在可选中。
optional 在内部保留存储所需大小的缓冲区Base
。即使与(如您的情况Base
一样)大小相同,Derived
它也只会存储Base
.
编辑:
以上答案是针对包含以下代码的原始问题给出的:
int main () {
boost::optional x(Derived());
func(x);
}
由于两个原因,此类代码不正确:
boost::optional
需要模板参数我忽略了这些问题,并假设这样的事情是这样的:
int main () {
boost::optional<Base> x = Derived();
func(x);
}
虽然该代码确实编译(至少 Visual Studio 2013 和 Boost 1.60)并导致切片。通过运行以下程序可以看出:
#include <boost/optional.hpp>
#include <iostream>
class Base
{
public:
virtual ~Base() { std::cout << "~Base" << std::endl; }
};
class Derived : public Base
{
public:
virtual ~Derived() { std::cout << "~Derived" << std::endl; }
};
int main()
{
boost::optional<Base> x = Derived();
}
产生输出
~派生 ~基地 ~基地
第二个~Base
表明optional
破坏Base
对象而不是Derived
对象。(与第一个一样~Derived
来自临时对象。)Derived()
~Base