我可以在抽象类中拥有静态数据成员吗?

时间:2011-06-17 14:06:54

标签: c++ abstract-class static-members

我设计了一系列相关的类,为了能够管理它们,我使它们来自一个抽象类。

这些类都需要访问一系列共享资源,我发现自己在每个中都创建了一个指针向量,所有这些都是相同的(它们必然是必须的)。看起来在基类中创建一个静态成员会给所有派生类访问这个向量,这意味着我只需要构建它一次(它不会在它构建之后改变,只是查找)。

我的问题是,如果这样可以,如果是这样,我怎样才能构建它,而不从其中一个派生类调用'填充矢量'方法?

我的想法是做一些像

这样的事情
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向量,这就是我想要的。

这会有用吗?这太可怕了吗?可以吗?

7 个答案:

答案 0 :(得分:0)

它可以工作,其中work = compile&amp;运行

但是,所有子类都将访问相同的静态向量,这意味着每个子类不会有静态向量的不同副本。

为了更好地解释我的意思,请阅读以下内容:

Are static fields inherited?

解决方案:

一种解决方案是让您的父类成为模板类,如下所示:

template<T>
class Parent<T> {
    public:
        static std::vector<T> sharedResource_;
}

class ChildA : Parent<ChildA> {
}

class ChildB : Parent<ChildB> {
}

在上面的代码中,您将获得ChildA的所有实例的共享资源以及ChildB的实例之间共享的另一个资源。

是不是?

嗯,我认为这不算好。对此的一个相关讨论是对以下SO问题的评论以及我对该问题的回答:

How to do "static overloaded const" in C#?

答案 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)

我在这里几点。

  • 您的矢量可能大小为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();
}