class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
将func接受两个选项:base和derived?
答案 0 :(得分:4)
不,它不会起作用。 func
对boost::optional<Base>
采用左值引用。这意味着它可以接受boost::optional<Base>
类型的左值,这是一种从boost::optional<Base>
公开且明确地派生的类型的左值,或者是具有operator boost::optional<Base>&()
的其他类型的左值。 boost::optional<Derived>
中没有一个是真的。类模板在C ++类型系统中不是coavrant - boost::optional<Derived>
不从boost::optional<Base>
继承。
如果func
按价值采用其论证,那将是另一回事。如果它看起来像:
void func(boost::optional<Base> ) { }
在这种情况下,您可以使用func
来呼叫boost::optional<Derived>
。但是转换构造函数标记为explicit
,因此您必须编写:
func(boost::optional<Base>{x});
这很明确 - 你明确表示你(可能)切片x
。
答案 1 :(得分:-1)
即使它可以工作(这可能是我还没有检查过),它会导致切片。只有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();
}
产生输出
~Derived ~Base ~Base
第二个~Base
表示optional
会破坏Base
个对象而不是Derived
个对象。 (~Derived
来自临时对象Derived()
,与第一个~Base
一样。)