在使用多态时如何“反转”继承?

时间:2016-01-12 09:29:55

标签: c++ inheritance

我在C ++中有一个工作设计,如下所示:

struct E {
    int some_properties ;
    // … some more
};

class A {
    public:
        void tick() {
            std::swap(futur, past) ;
        }

        void do_something() {
            // do something (read past, write futur)
            futur->some_properties = past->some_properties + 1 ;
        }

        E* past ;
   protected:
        E* futur ;
};    

现在,我想创建一个class B,使用新的class A方法继承void do_other_thing(),并使用struct F继承struct E新的int some_other ;属性。

方法void do_other_thing()可以是例如:

void do_other_thing() {
    // do something (read past, write futur)
    futur->some_properties = past->some_properties + past->some_other ;
    futur->some_other = past->some_other + 1 ;
}

我对如何实现这种继承感到非常困惑。

特别是在实现这种用例时:

// A a ;
a.tick() ;
a.do_something() ;

并且:

// B b ;
b.tick()
b.do_something() ;
b.tick() ;
b.do_other_thing() ;

问题出现了:

  • 这是否可能?

  • 如果是,怎么做?

  • 如果没有,如何以更好的结构解决问题?

编辑:

如上所述,最简单的继承模式将是:

class B : public A {
    void do_other_thing(){ // Something }
}

struct F : public E {
    int some_other;
}

遇到的问题是pastfutur这里是E指针:

void do_other_thing() {
    // do something (read past, write futur)
    futur->some_properties = past->some_properties + past->some_other ;
    futur->some_other = past->some_other + 1 ;
}

2 个答案:

答案 0 :(得分:1)

你可以dynamic_cast

void do_other_thing() {
    F* futur_f = dynamic_cast<F*>(futur);
    F* past_f = dynamic_cast<F*>(past);
    assert(futur_f && past_f);
    futur_f->some_properties = past_f->some_properties + past_f->some_other ;
    futur_f->some_other = past_f->some_other + 1 ;
}

或者你可以使用B中的第二对指针成员指向与futurpast相同的对象(更多数据,更少的转换 - 基本上缓存运行时强制转换)

或者您可以使用模板基类,其中pastfutur的类型是模板参数(有时需要引入非模板化的“根类”并使所有内容都是虚拟的)。

可能还有其他一些方法,有不同的权衡,好处和复杂性。

选择什么取决于您的计划的其余部分和您的个人喜好。

答案 1 :(得分:0)

首先,是的,这是可能的。以下只是用于说明的伪代码:

class B : public A {
    void do_other_thing(){ std::cout << "Other" << std::endl; }
}

struct F : public E {
    int some_other;
}

现在这两种新类型都将遵循能够取代其父类型的原则。这是通过指向其基类型(多态)的指针来实现的。

std::shared_ptr<A> baseARefToB{ std::make_shared<B>() };
baseRefToB->do_something();

std::shared_ptr<E> baseERefToF{ std::make_shared<F>() };
baseERefToF->some_properties = 3;

请注意,我无法通过基类引用访问其子类方法和属性。但是:

std::static_pointer_cast<B>(baseRefToB)->do_other_thing(); 
std::static_pointer_cast<E>(baseERefToF)->some_other = 42; 

这里我将对它们的基类型的引用强制转换,以便我可以访问它们的子类特定功能。

因此,从您的问题描述中,您将能够(始终)为所有类型的do_somethingsome_properties调用基类功能(AE),但如果通过具有正确类型的指针引用对象,则只能访问子类功能。