boost optional 承认继承?
boost optional recognizes inheritance?
class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
func 会接受两个可选值:base 和 derived 吗?
即使它可以工作(这很可能是我没有检查过的),它也会导致切片。只有 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
和第一个 ~Base
来自临时对象 Derived()
。)
不,它不会起作用。 func
接受对 boost::optional<Base>
的左值引用。这意味着它可以接受 boost::optional<Base>
类型的左值,公开且明确派生自 boost::optional<Base>
的类型的左值,或具有 operator boost::optional<Base>&()
的其他类型的左值。 None boost::optional<Derived>
是正确的。 Class 模板在 C++ 类型系统中不协变 - boost::optional<Derived>
不继承自 boost::optional<Base>
。
如果func
按价值来论证,情况就会不同。如果它看起来像:
void func(boost::optional<Base> ) { }
在那种情况下,您可以用boost::optional<Derived>
调用func
。但是那个转换构造函数被标记为 explicit
,所以你必须写:
func(boost::optional<Base>{x});
这是明确的好 - 你清楚地标记你正在(可能)切片 x
。
class Base {};
class Derived : public Base {};
void func(boost::optional<Base>&) {}
int main () {
boost::optional<Derived> x;
func(x);
}
func 会接受两个可选值:base 和 derived 吗?
即使它可以工作(这很可能是我没有检查过的),它也会导致切片。只有 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
和第一个 ~Base
来自临时对象 Derived()
。)
不,它不会起作用。 func
接受对 boost::optional<Base>
的左值引用。这意味着它可以接受 boost::optional<Base>
类型的左值,公开且明确派生自 boost::optional<Base>
的类型的左值,或具有 operator boost::optional<Base>&()
的其他类型的左值。 None boost::optional<Derived>
是正确的。 Class 模板在 C++ 类型系统中不协变 - boost::optional<Derived>
不继承自 boost::optional<Base>
。
如果func
按价值来论证,情况就会不同。如果它看起来像:
void func(boost::optional<Base> ) { }
在那种情况下,您可以用boost::optional<Derived>
调用func
。但是那个转换构造函数被标记为 explicit
,所以你必须写:
func(boost::optional<Base>{x});
这是明确的好 - 你清楚地标记你正在(可能)切片 x
。