我设计了一系列相关的类,为了能够管理它们,我使它们来自一个抽象类。
这些类都需要访问一系列共享资源,我发现自己在每个中都创建了一个指针向量,所有这些都是相同的(它们必然是必须的)。看起来在基类中创建一个静态成员会给所有派生类访问这个向量,这意味着我只需要构建它一次(它不会在它构建之后改变,只是查找)。
我的问题是,如果这样可以,如果是这样,我怎样才能构建它,而不从其中一个派生类调用'填充矢量'方法?
我的想法是做一些像
这样的事情class Resource {};
enumR {RES0, RES1};
class AbstractClass
{
public:
virtual void OnInit() = 0;
void static fillVector(Resource* pResource, enumR Resourcename)
{lResource[Resourcename]=pResource;};
protected:
static vector<Resource*> lResource;
};
vector<Resource*> AbstractClass::lResource;
int main()
{
Resource res0, res1;
AbstractClass::fillVector(&res0, RES0);
AbstractClass::fillVector(&res1, RES1);
return 0;
};
然后当我实例化从AbstractClass派生的任何类的对象时,我可以访问lResource向量,这就是我想要的。
这会有用吗?这太可怕了吗?可以吗?
答案 0 :(得分:0)
它可以工作,其中work = compile&amp;运行
但是,所有子类都将访问相同的静态向量,这意味着每个子类不会有静态向量的不同副本。
为了更好地解释我的意思,请阅读以下内容:
解决方案:
一种解决方案是让您的父类成为模板类,如下所示:
template<T>
class Parent<T> {
public:
static std::vector<T> sharedResource_;
}
class ChildA : Parent<ChildA> {
}
class ChildB : Parent<ChildB> {
}
在上面的代码中,您将获得ChildA的所有实例的共享资源以及ChildB的实例之间共享的另一个资源。
是不是?
嗯,我认为这不算好。对此的一个相关讨论是对以下SO问题的评论以及我对该问题的回答:
答案 1 :(得分:0)
更好的解决方案是只使用向量创建一个对象,然后只实例化一次,并为其他类指定或引用它。除非必要,否则应绝对避免使用静态数据,这不是必需的。
答案 2 :(得分:0)
您可以添加静态函数来初始化静态向量:
class AbstractClass
{
private:
// Add this
static vector<Resource*> CreateResources();
protected:
static vector<Resource*> lResource;
};
vector<Resource*> AbstractClass::lResource = CreateResources();
vector<Resource*> AbstractClass::CreateResources()
{
vector<Resource*> resources;
resources[RES0] = new Resource();
resources[RES1] = new Resource();
return resources;
}
答案 3 :(得分:0)
您可以尝试使用boost :: assign :: list_of,如下所示:
vector<Resource*> AbstractClass::lResource = list_of( &res0 )( &res1 );
答案 4 :(得分:0)
我在这里几点。
答案 5 :(得分:0)
由于您正在创建“资源指针”的向量而不预先为对象保留空间,因此您的系统将来可能会崩溃。为什么? 当您插入元素并使用相同的块直到它达到其capcity时,Vector会创建一个内存块。一旦它达到其capcality并且你插入一个新元素,vector将分配一个新的内存(两倍于之前分配的内存)并将所有现有元素复制到新内存中。由于这是“指针”的向量,因此它将无效地引用所有引用。
答案 6 :(得分:0)
在这些情况下我通常做的是添加一个中间模板层,所以我有这样的结构:
定义您的抽象界面:
class A
{
public:
virtual ~A(){}
virtual void f() = 0
virtual A* Clone() const = 0
}
将子项常用资源放在模板中,并在必要时使用CRTP定义样板函数,保持必要的接口函数仍然是抽象的
template<class Derived>
class A_T: public A
{
public:
virtual void f() = 0;
virtual A* Clone const
{
return new Derived(dyn_cast<Derived&>(*this))
}
void ManageRes();
private:
vector myResource;
}
最后,不同的具体类完成了实现,并在必要时对这些资源做了一些特殊的处理
class Child: public A_T<Child>
{
public:
void foo();
}