想象一下,我有一个“BaseA”类,其中包含项目'ItemA'的集合。 现在我想扩展'BaseA'以增加额外的功能,所以我从'BaseA'派生'DerivedA'。 'DerivedA'的一个特点是它必须处理更复杂的'DerivedITemA'项而不是'ItemA'项。
class BaseA {
protected:
vector<ItemA> x;
void m1(int i) { x.m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
现在我想处理这类事情:
class DerivedA : public BaseA {
vector<DerivedItemA> x;
void m2(int i) { x[i].m2(); }
};
即。让我的Derived类处理派生项。上面的x定义是不正确的,因为它与BaseA中的那个冲突。但我的想法是,我希望能够重用BaseA中处理x的所有方法,只要它们处理ItemA元素并在DerivedA中使用扩展方法来处理DerivedItemA类型数据的额外复杂性
有什么建议吗?我目前的想法是为x定义一个新的数据类型(例如VectorOfItemA)并从它派生VectorOfDerivedItemA。我想知道是否有更简单/更好的解决方案。
由于
答案 0 :(得分:0)
我相信你需要在你的向量中有指针才能处理这个问题。我有点困惑传递给m1和m2的值,因为我似乎是一个索引,但这是我的猜测:
class BaseA {
protected:
vector<ItemA*> x;
void m1(int i) { x[i]->m1(i); }
};
class ItemA {
protected:
void m1(int i) { ... }
};
class DerivedItemA : public ItemA {
void m2(int i) { ... }
};
class DerivedA : public BaseA {
vector<DerivedItemA*> y; //don't shadow the base class vector!
void m2(int i) { y[i]->m2(i); }
};
然后,当您在DerivedA中添加项目时,将其添加到x和y。这样BaseA可以对x中的指针执行操作,DerivedA可以在y中的指针上执行此操作。
编辑:您还需要提供一个虚拟方法来添加项目,否则您可能会将添加到BaseA.x的内容添加到DerivedA.y中。
答案 1 :(得分:0)
您可以尝试使用奇怪的重复模板模式 - CRTP:
#include <iostream>
#include <ostream>
#include <vector>
using namespace std;
struct Item
{
void m1(int i)
{
cout << "m1(" << i << ")" << endl;
}
};
struct DerivedItem : Item
{
void m2(int i)
{
cout << "m2(" << i << ")" << endl;
}
};
template<typename Derived>
struct IBase
{
void m1(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m1(i);
}
}
};
template<typename Derived>
struct IDerivedBase: IBase<Derived>
{
void m2(int i)
{
for(auto &&z : static_cast<Derived*>(this)->x)
{
z.m2(i);
}
}
};
struct Base : IBase<Base>
{
vector<Item> x;
};
struct DerivedBase : IDerivedBase<DerivedBase>
{
vector<DerivedItem> x;
};
int main()
{
Base b;
b.x.resize(3);
DerivedBase d;
d.x.resize(1);
b.m1(11);
d.m1(22);
d.m2(33);
}
输出是:
m1(11)
m1(11)
m1(11)
m1(22)
m2(33)
Vector将在BaseA实例化中包含所有元素作为ItamA,或者在DerivedA实例中包含DerivedItemA的所有元素。没有必要混合。
这种方法没有任何组合:
但是,如果不了解真实的使用模式 - 很难猜出你需要什么。也许对于你的情况,两个独立的向量就足够了:
vector<Item> x1;
vector<DerivedItem> x2;
并为它们定义独立的功能。
答案 2 :(得分:0)
你拥有所有课程吗?如果是这样,您可以改为重构为模板基类。
template <typename ITEM>
class BaseT {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
};
typedef BaseT<ItemA> BaseA;
class DerivedA: public BaseT<DerivedItemA> {
void m2(int i) { x[i].m2(); }
};
如果您打算重复使用BaseA
同时接受DerivedA
的代码,那么您可能需要将它们修改为模板函数/类。
否则,您将需要某种矢量的“多态”基础对象。您可以查看Retrieve data from heterogeneous std::list(或我的后续问题:unique_ptr member, private copy constructor versus move constructor),了解其中一种方法。
作为多态项目的替代方案,您可以为基础定义接口。
class BaseI {
protected:
virtual void m1(int) = 0;
//... other interfaces
public:
virtual ~BaseI () {}
//... other public interfaces
};
template <typename ITEM>
class BaseT : public BaseI {
protected:
vector<ITEM> x;
void m1(int i) { x[i].m1(); }
//...implement the other interfaces
};
//...
现在,需要重构代码BaseA
以取代BaseI
。新代码也可以接受DerivedA
。