简体   繁体   English

如何通过交叉广播恢复接口

[英]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 by T . 否则,将应用运行时检查以查看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 a T object, and if only one object of type T is derived from the sub-object pointed (referred) to by v , the result is a pointer (an lvalue referring) to that T 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 type T , that is unambiguous and public , the result is a pointer (an lvalue referring) to the T 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM