当没有涉及虚函数时,有没有办法从虚拟基类转发到派生类?这里有一些代码来演示我在说什么:
struct Base1
{
int data;
};
struct Base2
{
char odd_size[9];
};
struct ViBase
{
double value;
};
struct MostDerived : Base1, Base2, virtual ViBase
{
bool ok;
};
void foo(ViBase &v)
{
MostDerived &md = somehow_cast<MostDerived&>(v); //but HOW?
md.ok = true;
}
int main()
{
MostDerived md;
foo(md);
}
Run Code Online (Sandbox Code Playgroud)
请注意,该代码仅用于演示.我的真实场景相当复杂,涉及模板参数和从一个到另一个的转换,只知道第一个是第二个的基础; 它可以是普通或虚拟的基础,它可能有也可能没有虚函数.(参见底部的简化示例).我可以使用类型特征检测多态情况和虚拟/非虚拟基本情况,并解决除非多态虚拟基础之外的所有情况.这就是我要问的问题.
我真的想不出一种做演员的方法:
隐含的转换是正确的; 这些只做了预告.
static_cast 明确禁止从虚拟基类进行转换:
5.2.9/2 ...并且
B既不是虚拟基类,D也不是虚基类的基类D....
dynamic_cast 也不能这样做,因为downcast需要一个多态类
5.2.7/6否则,
v应该是指向多态类型的指针或glvalue(10.3).10.3/1 ...声明或继承虚函数的类称为多态类.
reinterpret_cast 在这里根本不适用.
如果 …
为什么需要(为了使其编译)中间体CloneImplementation和std::static_pointer_cast(参见下面的第3节)使用克隆模式std::shared_ptr而不是更接近(参见下面的第2节)使用原始指针(参见下面的第1节)?因为据我所知,std::shared_ptr有一个广义的复制构造函数和一个广义的赋值运算符?
1. 带有原始指针的克隆模式:
#include <iostream>
struct Base {
virtual Base *Clone() const {
std::cout << "Base::Clone\n";
return new Base(*this);
}
};
struct Derived : public Base {
virtual Derived *Clone() const override {
std::cout << "Derived::Clone\n";
return new Derived(*this);
}
};
int main() {
Base *b = new Derived;
b->Clone();
}
Run Code Online (Sandbox Code Playgroud)
2. 共享指针的克隆模式(幼稚的尝试):
#include <iostream>
#include <memory>
struct Base {
virtual std::shared_ptr< Base > …Run Code Online (Sandbox Code Playgroud) 我正在查看cppreference文档,std::unique_ptr并注意到C++ 17似乎已经做了一些有趣的更改.特别是,std::unique_ptr<T[]>现在的特化接受模板参数,它之前只接受std::unique_ptr::pointer参数.例如,以下是其中一个reset成员函数的声明std::unique_ptr<T[]>:
template <typename U> void reset(U p);
Run Code Online (Sandbox Code Playgroud)
该网站声明:
行为一样的
reset主模板的成员,但它只会参与重载分辨率如果任U是相同的类型pointer,或者pointer是相同的类型element_type*和U是指针类型V*,使得V(*)[]可转换为element_type(*)[].
我假设这是为了安全 - 你不想delete[]在指向指向其基类型指针的派生类型数组的指针上执行(在C++ 17之前,这被标记为已删除) .正如所料,此代码编译良好:
#include <type_traits>
struct foo {};
struct bar : public foo {};
static_assert(!std::is_convertible_v<bar(*)[], foo(*)[]>);
Run Code Online (Sandbox Code Playgroud)
然而,有趣的是,以下内容无法编译,两者都失败static_assert:
#include <type_traits>
struct foo {};
struct bar : public foo {};
static_assert(std::is_convertible_v<bar*(*)[], foo*(*)[]>);
static_assert(std::is_convertible_v<std::unique_ptr<bar>(*)[], std::unique_ptr<foo>(*)[]>); …Run Code Online (Sandbox Code Playgroud)