在派生类中处理派生对象集合的最佳方法是什么?
What is the best way to handle a collection of derived objects in a derived class
假设我有一个类'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(); }
};
。让我的派生类处理派生项。上面x的定义是不正确的,因为它与BaseA中的定义冲突。但我的想法是,我希望能够重用BaseA中处理x的所有方法,只要它们处理ItemA元素并在DerivedA中具有扩展方法来处理DerivedItemA数据类型的额外复杂性
任何建议吗?我目前的想法是为x定义一个新的数据类型(例如VectorOfItemA),并从中派生VectorOfDerivedItemA。我想知道是否有一个更简单/更好的解决办法。
谢谢
我相信你需要在你的向量中有指针来处理这个问题。我有点困惑什么值传递给m1和m2,因为I似乎是一个索引,但这是我的猜测:
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的东西。
你拥有所有的类吗?如果是这样,你可以重构成一个模板基类。
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
的代码,那么你可能需要将它们修改为模板函数/类。
否则,您将需要向量的某种"多态"基对象。您可以查看从异构std::list中检索数据(或者我的后续问题:unique_ptr成员,私有复制构造函数与移动构造函数)来获取这样一种方法。
作为多态物品的替代品,你可以为你的基类定义一个接口。
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
。
您可以尝试使用好奇循环模板模式- 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的所有元素,或者包含DerivedItemA实例化中DerivedA的所有元素。没有必要混在一起。
在这种方法中没有任何混合:
- Base只有vector<<strong>Item>提供m1方法
- DerivedBase只有vector<<strong>DerivedItem>提供m1和m2方法。
然而,如果不知道真正的使用模式-很难猜测您需要什么。也许对于您的情况,两个独立的向量就足够了:
vector<Item> x1;
vector<DerivedItem> x2;
并为它们定义独立的函数
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 派生类销毁的最佳实践是什么
- 在派生类中使用基类的私有成员变量的最佳方法
- 调用不属于基类的派生类函数的最佳方法是什么?
- 将指针从派生到基类的方法的最佳方法
- 最佳做法:将派生类的向量传递给基类向量上的方法
- 在 QList 中访问派生类时的最佳做法
- 最佳实践:访问向量中具有不同成员变量和方法的派生类
- 派生类方法的默认参数的最佳实践
- 管理指向派生对象的指针集合的最佳方式
- 根据用户输入创建相应的派生类的最佳实践是什么?
- 拥有所有派生自同一基类的类实例集合的最佳方法是什么?
- c++中派生类携带不同数据类型的最佳方式
- 从基类更改为派生类的最佳方法
- 在派生类中处理派生对象集合的最佳方法是什么?
- 在c++中使用派生类的最佳实践
- 通过基类容器访问派生类唯一变量的最佳方式