我有一个 Base 类和许多派生类(即 DerivedX )作为生产代码。 在不触及这些类的情况下,我创建了一个从Base派生的 BaseExt 类,以便为了测试目的而操纵内部数据。
+-----------+ +-----------+
| 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 来完成同样的工作,但是我有很多这样的派生类,只为一个简单的任务添加了太多的代码。
问题是
答案 0 :(得分:1)
模板怎么样?
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;
}
}
或者,如果您准备更改源,使得每个派生类实际上都继承自Base
(即class DerivedX : public virtual Base
),那么我认为您可以将其与多重继承混合以获得'测试期间的额外方法'(我还没有测试过):
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);
}