0
class BaseClass {
public:
  BaseClass(const byte *buff, long size) { 
     // Some Computation
  }
};

class DerivedClass: public BaseClass {
public:
  std::vector<byte> filebuff;
  long buff_size;
  DerivedClass(): BaseClass(/*How should I send stuff here?*/) 
  { 
  }
  /*return type??*/  cal_func(){
   // Some computation involving file descriptors.
   // Store result in filebuff. Store size of filebuff in buff_size.
    return /*what??*/;
  }
}

I can only think of the following solution:

 DerivedClass(): BaseClass(&filebuff[0], cal_func) 

In the above case, I will make function func() to return length of filebuff. I am relying on the fact that filebuff is only an address and hence it doesn't matter whether the compiler puts the computed value of func on the stack first or the first arg, filebuff.

Please tell me whether this is a correct method for doing so. If the first argument wasn't an address and some other computed value which would've required the computation carried out in the function func, what would be the best way to go about it?

Nehal J Wani
  • 16,071
  • 3
  • 64
  • 89

2 Answers2

2

It looks like you are trying to wrap a class that someone else wrote (e.g. in a different library), which takes two arguments, with another class (that you wrote) that has a cleaner interface. Am I correct?

Your proposed solution is to derive from the other base class and then use the derived class to store the arguments that are put in the base class. The problem with your approach above is that, when you are calling the base class constructor, the derived class has not yet been fully constructed yet (i.e. filebuff and bufsize cannot be guaranteed to have been initialized to anything).

I suggest an alternative approach, where instead of deriving, you have a WrapperClass that contains the base class, as well as the two data members you have, like so:

class Wrapper {
public:
  Base base;
  std::vector<byte> filebuff;
  long buff_size;
  Wrapper();
}

So in the constructor of the wrapper class, you can do the following:

WrapperClass::WrapperClass() {
  //do whatever you want to initialize filebuff and buffsize here
  calcfunc();

  //now pass them in to your base class
  base = Base(filebuff, buffsize);
}

[Edit]

Alternative

The above solution assumed that your base class has a default constructor, i.e. Base(). It may be that it doesn't, and that you can't create one. If so, then the code above won't compile because there is no way to default-initialize the base member variable. An alternative is to use a pointer to the Base class such as Base*, or std::unique_ptr<Base>, or some such mechanism instead of a Base member directly. This way, you control exactly when the Base class gets initialized. So:

//class definition
class Wrapper {
public:
  std::unique_ptr<Base> base;
  std::vector<byte> filebuff;
  long buff_size;
  Wrapper();
}

//...

//constructor implementation
WrapperClass::WrapperClass() {
  //do whatever you want to initialize filebuff and buffsize here
  calcfunc();

  //now pass them in to your base class
  base = new Base(filebuff, buffsize);
}
maditya
  • 8,626
  • 2
  • 28
  • 28
  • 2
    Why `Base*` and not `Base`? BTW your code violates the rule-of-three. – ildjarn Mar 29 '13 at 23:46
  • Fair enough. I was just trying to offer a alternative using composition instead of inheritance. I'll edit to use Base. – maditya Mar 29 '13 at 23:48
  • Actually, I just realized that depends on whether or not the base class has a default constructor defined for initialization... – maditya Mar 29 '13 at 23:52
  • @maditya the assumption is it does *not*, and thus the best-reason to support your initial intention of dynamic composition (though I would use a `std::unique_ptr`). – WhozCraig Mar 29 '13 at 23:56
2

The problem is that you are trying to use filebuff before it has been initialized because the constructors of the base classes are called before the constructors of non-static members. I agree with ildjarn that the best solution is to replace inheritance with composition here:

class BaseClass {
public:
  BaseClass(const byte *buff, long size) { 
     // Some Computation
  }
};

class YourClass {
public:
  std::vector<byte> filebuff;
  long buff_size;
  BaseClass base;

  DerivedClass()
    : /* initialize filebuff and buff_size */, base(&filebuff[0], buff_size) {}
};

The members will be initialized in the order they appear in the class definition so you'll be able to pass filebuff and buff_size to the base's constructor.

See also this answer to the question "C++: Initialization Order for Member Classes".

Community
  • 1
  • 1
vitaut
  • 49,672
  • 25
  • 199
  • 336
  • 1
    The only thing i'd really change in this is losing the filesize entirely and just sizing the vector as needed, casting into the base class with `base(filebuff.data(), (long)filebuff.size())`, but the overall premise is good if you can get the buffer properly sized in the initializer list. All in all, a good approach. – WhozCraig Mar 30 '13 at 00:03