铸造 sibling class 有充分的理由吗?

Casting sibling class with a good reason?

我有一个 Base class 和很多派生的 classes(即 DerivedX)作为生产代码。 在不触及那些 classes 的情况下,我创建了一个从 Base 派生的 BaseExt class,以便为测试目的操纵内部数据。

+-----------+            +-----------+
| Base      + <- - - - - | BaseExt   |
+-----------+            +-----------+
   /|\
    |
+-----------+
| DerivedX  +
+-----------+

这是代码示例

      class Base {
      public:
        int data() const { return _data; }
      protected:
        Base() = default;
        virtual ~Base() = default;
        int _data;
      };

      class Derived1 : public Base {
      };

      class BaseExt : public Base {
      public:
        void inject_data(int data) { _data = data; }
      };

它对我来说很直观。

    std::shared_ptr<Base> p = std::make_shared<Derived1>();
    auto d1 = p->data(); // 0
    std::static_pointer_cast<BaseExt, Base>(p)->inject_data(10);
    auto d2 = p->data(); // 10

基线:我不想更改我的生产代码(即 Base 和 DerivedX)

当然我可以扩展 Derived1 来做同样的工作,但是我有很多这样的派生 classes,它们添加了太多的代码,只是一个简单的任务。

问题是

模板呢?

template<typename T>
struct TestableDerived : T {

    inject_data(int data) {
        _data = data;
    }

    static std::shared_ptr<Base> createAndInjectData(int data) {
        std::shared_ptr<TestableDerived<T>> ptr = std::make_shared<TestableDerived<T>>();
        ptr->inject_data(data);
        return ptr;
    }
}

或者,如果您准备更改您的来源,使每个派生的 class 实际上继承自 Base(即 class DerivedX : public virtual Base),那么我认为您可以将其与多重继承只得到 'an extra method during testing' (我还没有测试过):

struct BaseExt : virtual Base {
    void inject_data(int data) { _data = data; }
}

template<typename T>
struct TestDerived<T> : virtual T, virtual BaseExt {}

void doSomeTesting() {
    std::shared_ptr<TestDerived<DerivedX>> p1 = std::make_shared<TestDerived<DerivedX>>();
    std::shared_ptr<DerivedX> p2 = p1;
    std::shared_ptr<BaseExt> p3 = p1;

    assert(p1->data()==0);
    assert(p2->data()==0);
    assert(p3->data()==0);

    p3->inject_data(10);

    assert(p1->data()==10);
    assert(p2->data()==10);
    assert(p3->data()==10);
}