tags:

views:

158

answers:

2

Here's the scenario: I want define a base class that allocate some buffer once for all derived classes, while the size of the buffer varies among different derived classes. I could achieve it in this way:

class base
{
public:
     base():size(), p_array(0){}
private:
     size_t size;
     boost::shared_array<unsigned char> p_array;

};

in the derived class:

class derived
{
public:
     derived(size_t array_size):size(array_size)
     {
          p_array.reset(new unsigned char[size]);
     }    
};

However, in order to simplify the design of the derived class, I really want to put this line:

p_array.reset(new unsigned char[size]);

to somewhere in the base class, thus writing it only once. Is there any C++ design pattern could achive it? Thanks.

+4  A: 

sorry but why do you have 2 arrays (and 2 sizes)? Now if you create a derived class you have a 2 times a p_array. I think the compiler should give an error on this.

Don't you want this?

class base
{
public:
     base():size(), p_array(0){}
     base(size_t array_size):size(array_size)
     {
          p_array.reset(new unsigned char[size]);
     }
private:
     size_t size;
     boost::shared_ptr<unsigned char> p_array;

};

class derived
{
public:
     derived(size_t array_size):base(array_size)
     {
     }
private:
};
PoweRoy
You are right, I just copied over the base class lines and modified it while drafting the the derived class. Corrected, Thanks.
t.g.
You code has the very problem I wish avoid in my question.p_array has been allocated already when you re-assign a value in the derived class to the member size, and from this point the member size does not equal to the size of allocated buffer any more.
t.g.
can you use vectors? It will make this problem easier to solve
PoweRoy
No, because I need to cast it to a C pointer so as to feed into a C-style Win32 API. In fact, I am wrapping that API in C++.Vectors are dynamic, but they don't cast to C arrays naturally.
t.g.
Alex Che
Actually, this answer seems to be correct, since p_array is reset to size, passed from derived class. This happens in base class' constructor and only once.
Alex Che
Ah, yes, it's the correct answer. I just missed the point in my read glance: by treating size as a parameter in both ctors. it will be passed from the ctor of the derived class to that of the base class, and it's done during the constructing of the base class.
t.g.
Casting from vector in your ways should work. Somehow I just feel it's not natural, since the buffer may be out of control of the vector, I suspect some member functions won't work correctly afterwardst(I have no proof for this). I have no problems if they are allocated as arrays in the first place.
t.g.
+3  A: 

You can pass the size to the base class' constructor:

class base
{
   base(size_):size(size_), p_array(new char[size_]) {}
}

Your derive class determines the size, though it needs to know it upon base construction:

class largebufferderived : public base
{
   public:
     largebufferderived() : base(77220) {}
}


Or you can initialize the buffer on demand (that's not always a good idea in multithreaded scenarions):

boost::shared_ptr<char> Buffer() 
{
   if (!p_Array)
     p_array.reset(new unsigned char[size]);
}

Make p_Array private in the base class, so derived classes can access only through Buffer().


Alternatively, just add a "FinalConstruct" methood to call in the derived classes Constructors. Thi does not avoid calling it, but at least isolates WHAT needs to be done after all constructors were called.

btw. why shared_ptr, not shared_array?

peterchen
Yes I was thinking of boost::shared_array while I wass typing. Corrected now.The way you suggested is exactly what I wanted to avoid. I wished to achieve this:1) the buffer is allocated inside the base class while2) the size is designated inside the derived class.
t.g.
By resetting p_array in the derived the class could work but no good, because 1) I may forgot to reset it thus causing buffer overflow 2) the buffer is allocated twice in theory(once in the base and theother in the derived), and the 1st one is wasted.
t.g.
In both cases, resetting p_array is done in the base class, while size is determined in the derived. Note that, in the first example, you can do argument-dependent arithmetics, even call a static function to determine the size.
peterchen
Also, in suggestion 1, you cannot inherit without providing a constructor that initializes size (since the explicit constructor hides the default).
peterchen
The 1st suggestion is what I am looking for. Thanks. In my case, the allocated buffer must be public to be access to outside as a Win32 API parameter,so Solution 2 won't apply here.
t.g.