[英]How to recover an interface through crosscast
First base class 一等座
class Io_obj
{
public:
virtual Io_obj* clone() const=0;
virtual ~Io_obj(){}
};
First derived class 一阶派生类
template<typename T>
class Io : public Io_obj,T
{
public:
Io(){}
Io(string& s){cout << s << '\n';}
Io* clone() const override {return new Io{*this};}
static Io* new_io(string& s){return new Io{s};}
};
Second base class 二等座
class Shape
{
public:
virtual void draw() const=0;
virtual ~Shape(){}
};
Second derived classes 二次派生类
class Circle : public Shape
{
public:
Circle(){}
Circle(string& s){cout << s << '\n';}
void draw() const override{cout << "draw circle\n";}
};
class Triangle : public Shape
{
public:
Triangle(){}
Triangle(string& s){cout << s << '\n';}
void draw() const override {cout << "draw triangle";}
};
main functions 主要功能
using io_circle = Io<Circle>;
using io_triangle = Io<Triangle>;
using Pf = function<Io_obj*(string&)>;
map<string,Pf> io_map{{"circle",&io_circle::new_io},{"triangle",&io_triangle::new_io}};
Io_obj* get_obj(string& s){
if(auto f=io_map[s]) return f(s);
throw runtime_error{"error: wrong type"};
}
int main(){
vector<string> vs{"circle","triangle","square"};
for(auto x:vs){
unique_ptr<Io_obj> my_obj{get_obj(x)};
if(auto sp=dynamic_cast<Shape*>(my_obj.get())){
sp->draw();
}else{
throw runtime_error{"error: bad cast"};
}
}
return 0;
}
Dynamic cast failed. 动态投射失败。 It seems that the object created by
unique_ptr<Io_obj> my_obj{get_obj(x)}
is of type Io_obj
, which has no member function draw()
. 看来由
unique_ptr<Io_obj> my_obj{get_obj(x)}
创建的对象的类型为Io_obj
,它没有成员函数draw()
。 How to make it work? 如何使其运作?
Code from Bjarne Stroustrup: the C++ programming language Ch22.2.4 Bjarne Stroustrup的代码:C ++编程语言Ch22.2.4
To fix this, change: 要解决此问题,请更改:
template<typename T>
class Io : public Io_obj, T
to: 至:
template<typename T>
class Io : public Io_obj, public T
Access specifiers must be written separately for each base type. 必须为每种基本类型分别编写访问说明符。 In your case, second derivation was
private
, as this is the default mode. 在您的情况下,第二个派生是
private
,因为这是默认模式。
dynamic_cast<>
converts Io<T>
to T
, if they are connected with is-a relation, which is created by public inheritation. 如果它们通过公共继承创建的is-a关系连接,
dynamic_cast<>
会将Io<T>
dynamic_cast<>
转换为T
In case of private, dynamic_cast<>
will not work, because Io<T>
is not T
(private inheritance creates relation called "implemented in terms of" ). 在私有的情况下,
dynamic_cast<>
将不起作用,因为Io<T>
不是 T
(私有继承会创建称为“根据...实现的”关系 )。
Test: http://coliru.stacked-crooked.com/a/130c7768fb5b501d 测试: http : //coliru.stacked-crooked.com/a/130c7768fb5b501d
Of course this code will also throw an std::runtime_error
, as you have not registered "factory" for square
type, but I guess you already know this :) 当然,此代码还会抛出
std::runtime_error
,因为您尚未为square
类型注册“ factory”,但我想您已经知道这一点了:)
Some reference, perhaps ( 18.5.2 - dynamic_cast<T>(v)
): 可能有些参考( 18.5.2 -
dynamic_cast<T>(v)
):
Otherwise, a run-time check is applied to see if the object pointed or referred to by
v
can be converted to the type pointed or referred to byT
.否则,将应用运行时检查以查看
v
指向或引用的对象是否可以转换为T
指向或引用的类型。The run-time check logically executes as follows:
运行时检查在逻辑上执行如下:
If, in the most derived object pointed (referred) to by
v
, v points (refers) to a public base class subobject of aT
object, and if only one object of typeT
is derived from the sub-object pointed (referred) to byv
, the result is a pointer (an lvalue referring) to thatT
object.如果,在最派生对象指向的(简称)至
v
,V点(指)到的公共基类子对象T
对象,并且如果只有一个类型的对象T
从子对象衍生指出(简称)到v
的结果是指向该T
对象的指针(一个左值引用)。Otherwise, if
v
points (refers) to a public base class sub-object of the most derived object, and the type of the most derived object has a base class, of typeT
, that is unambiguous and public , the result is a pointer (an lvalue referring) to theT
sub-object of the most derived object.否则,如果
v
指向(引用)最派生对象的公共基类子对象,并且最派生对象的类型具有类型T
的基类(即明确且公共的) ,则结果为指针(表示左值)到最派生对象的T
子对象。Otherwise, the run-time check fails.
否则,运行时检查将失败。
The value of a failed cast to pointer type is the null pointer value of the required result type.
转换为指针类型失败的值是所需结果类型的空指针值。 A failed cast to reference type throws
bad_cast
.转换为引用类型失败会抛出
bad_cast
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.