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

发布于 2024-11-15 23:12:41 字数 857 浏览 1 评论 0原文

我设计了一系列相关的类,为了能够管理它们,我让它们从一个抽象类派生。

这些类都需要访问一系列共享资源,我发现自己在每个类中创建了一个指针向量,它们全部相同(它们必然必须相同)。似乎在基类中创建一个静态成员将使所有派生类都可以访问该向量,这意味着我只需要构建它一次(构建后它也不会改变,只需查找)。

我的问题是这是否可以,如果可以,我如何构建它,而不从派生类之一调用“填充向量”方法?

我的想法是做类似的事情

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

这行得通吗?可怕吗?可以吗?

I designed a series of related classes, and in order to be able to manage them I made them derive from a single abstract class.

These classes all need access to a series of shared resources, and I found myself creating a vector of pointers in each, all of them identical (they necessarily must be). It seems like making a static member in the base class would give all of the derived classes access to this vector, meaning I need only build it once (it's not going to change either after it's been built, just looked up).

My question is if this is ok, and if so, how can I then build it, without calling a 'fill the vector' method from one of the derived classes?

My thinking was to do something like

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;
};

Then when I instantiate an object of any class derived from AbstractClass, I'd have access to the lResource vector, which is what I want.

Would this work? Is it horrible? Is it ok?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

不再见 2024-11-22 23:12:42

它会起作用,其中工作=编译&跑步。

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

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

静态字段是否继承?

解决方案:

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

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

class ChildA : Parent<ChildA> {
}

class ChildB : Parent<ChildB> {
}

在上面的代码中,您将获得 ChildA 的所有实例的共享资源,以及在实例<之间共享的另一个资源。 /em> 的儿童 B.

是吗?

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

如何执行“静态重载” C# 中的 const?

It would work, where work = compile & run.

However, all child classes will be accessing the same static vector, which means there won't be a different copy of the static vector for each child class.

For a better explanation of what I mean read the following So thread:

Are static fields inherited?

SOLUTION:

One solution is to have your parent class a template class as follows:

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

class ChildA : Parent<ChildA> {
}

class ChildB : Parent<ChildB> {
}

In the above code, you will get a shared resource for all instances of ChildA and another one shared between instances of ChildB.

Is it right?

Well, I think it is not considered good. One of the related discussions to this is in comments to the following SO question and also under my answer to the question:

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

放血 2024-11-22 23:12:42

更好的解决方案是只创建一个带有向量的对象,然后仅实例化它一次,并为其他类提供指向它的指针或引用。除非必要,否则绝对应该避免使用静态数据,而这并不是必要的。

The better solution would be to just make an object with the vectors in and then only instantiate it once and give the other classes a pointer or reference to it. Static data should be absolutely avoided unless necessary and this just isn't necessary.

自此以后,行同陌路 2024-11-22 23:12:42

您可以添加静态函数来初始化静态向量:

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;
}

You can add a static function to initialise your static vector:

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;
}
似狗非友 2024-11-22 23:12:42

您可以尝试 boost::assign::list_of ,如下所示:

vector<Resource*> AbstractClass::lResource = list_of( &res0 )( &res1 );

You could try boost::assign::list_of, something like this:

vector<Resource*> AbstractClass::lResource = list_of( &res0 )( &res1 );
一口甜 2024-11-22 23:12:42

我在这里有几点。

  • 您的向量的大小可能为 0。这可能会导致一些崩溃。您必须在使用之前分配它。您可以进行静态或全局初始化。
  • 你真的想要一个向量吗?当您使用某些动态内存分配时,向量是合适的。枚举是静态的。您可以给出一个简单的计数并将其分配为数组。
  • 你真的想要一个静态成员吗​​?静态成员通常在同一类的对象之间共享时使用。您可以使用类中本地/全局的外部对象来满足要求吗?您还可以在类中创建静态函数吗?

I have few points here.

  • Your vectory probably having size of 0. This could lead to some crash. You will have to allocate it before using. You can give a static or global initialize.
  • Do you really want a vector? Vector is appropriate when you're using some dynamic memory allocation. The enums are static. You can give a simple count and allocate it as an array.
  • Do you really want a static member? Static member usually used while you're sharing it between the objects of the same class. Can you satisfy the requirement with an external objects which is local/global within the class? Also can you make static function out of the class?
尹雨沫 2024-11-22 23:12:42

由于您正在创建“资源指针”向量并且没有提前为对象保留空间,因此您的系统将来可能会崩溃。为什么?
当您插入元素时,Vector 会创建一个内存块,并使用同一块,直到达到其容量为止。一旦达到其容量并且插入一个新元素,向量将分配一个新内存(是先前分配的内存的两倍)并将所有现有元素复制到新内存中。由于这是一个“指针”向量,因此它将使所有引用无效。

Since you are creataing the vector of "resource pointer" and not reserving the spaces for object in advance ,your sysetem might crash in future. Why?
Vector create a block of memory when you insert element and uses the same block until it hits its capcity. Once it hits its capcality and you inset a new element, vector will allocate a new memory (twice as previous allocated memory) and copies all the existing elements into new memory. Since this is a vector of "pointers", it is going to invaliadate all the refernces.

栀子花开つ 2024-11-22 23:12:42

在这些情况下,我通常做的是添加一个中间模板化层,这样我就有了这样的结构:

定义抽象接口:

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();
}

What I usually do in these cases is add a middle templated layer so I have a structure like this:

Define your abstract interface:

class A
{
public:
virtual ~A(){}

virtual void f() = 0 

virtual A* Clone() const = 0
}

Put the resources commonly used by the child in a template and define the boiler-plate function using CRTP if necessary keeping the necessary interface function still abstract

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;
}

Finally the different concrete classes complete the implementation and do something special with those resources if necessary

class Child: public A_T<Child>
{
public: 
void foo();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文