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> ) { }
在这种情况下,您可以使用. 但是那个转换构造函数被标记了,所以你必须写:funcboost::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