Can I have static data elements in an abstract class?

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

These classes all need access to a series of shared resources, and I found that I create a vector of pointers in each, they are all identical (they must be). It seems that creating a static member in the base class would give all derived classes access to this vector, that is, I only needed to build it once (it will not change even after it was built, just looked up).

My question is that this is normal, and if so, how can I then build it without calling the "fill 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 will have access to the lResource vector that I want.

Will this work? It's horrible? This is normal?

+4
source share
7 answers

The best solution would be to simply create an object with vectors, and then just create an instance of it and give other classes a pointer or a link to it. Static data should be avoided if necessary, and it is simply not necessary.

+1
source

This would work when work = compile and run.

However, all child classes will refer to the same static vector, which means that for each child class there will be no other copy of the static vector.

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

Inherited static fields?

DECISION:

One solution is to create the parent class of the 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 for instances of ChildB.

Is it correct?

Well, I think this is not considered good. One of the discussions related to this is in the comments on the next SO question, as well as under my answer to the question:

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

0
source

You can add a static function to initialize a 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; } 
0
source

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

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

I have a few points here.

  • Your folder probably has a size of 0. This can lead to some collapse. You will need to highlight it before use. You can specify static or global initialization.
  • Do you really need a vector? A vector is suitable if you use dynamic memory allocation. Enumerations are static. You can give a simple account and select it as an array.
  • Do you really need a static member? A static member is usually used when you share it between objects of the same class. Can you satisfy the requirement with external objects that are local / global within the class? Also can you make a static function outside the class?
0
source

Because you are creating a “resource pointer” vector and are not reserving space for an object in advance, your system may crash in the future. What for? A vector creates a block of memory when you insert an element and use the same block until it reaches its ability. As soon as it falls into its droplet and you insert a new element, the vector allocates a new memory (twice as much as the previous allocated memory) and copies all existing elements to the new memory. Since this is a vector of "pointers", it will activate all links.

0
source

What I usually do in these cases is to add a middle template layer so that I have such a structure:

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 the template and define the function of the boiler plate using CRTP, if necessary, while maintaining the necessary interface function

 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, various concrete classes complete the implementation and do something special with these resources, if necessary.

 class Child: public A_T<Child> { public: void foo(); } 
0
source

All Articles