You are here:

C++/shared constant base class/derived class dilemma



My question is about how to do something that should be simple, but classes/inheritance doesn't seem to allow, at least in a forward manner.

Let's say our sample application needs to process (open, read, close) text files that represent different types of data for the application (Customer, Vendor, Invoice).

I would think of implementing a base class with the functions Open(), Read(), and Close(), and then have a derived class for each type of specialized files (Cust, Vend, Invoice).

I'd like to have a constant static string for the FileType, so each derived class could define their type:

the FileType class would define it as "CUST"
the FileType class would define it as "VEND"
the FileType class would define it as "INVC"

Defining this member in the base class will allow to have the Open(), and other text-file-specific functionality in the base class b/c all derived classes are text files. The FileType string will be part of the file path or filename, so only the base's Open() needs to concatenate it as needed.

There will be a member called ProcessData(), which will be implemented in each derived class for class-specific processing. The processing sequence of the whole process would be:

Open()   // base class does this.
Read()   // base class does this.
ProcessData()   // derived classes implement this.
Close()   // base class does this.

But if I declare this static constant string in the base class, I cannot have different values for the FileType in each one of the derived classes.

I want it to be static, so it's one for each derived class instance.
I want it to be constant, so it doesn't have to be initialized at runtime.

Would you please explain to me the solution for this dilemma?

Thank you,


ANSWER: have a virtual function
    virtual const char* filetype_string() const = 0 ;
in the base class.

override it to return the filetype (a static const string) in each derived class.

call open (in the base class) *after* the object has been fully constructed.   

struct file_base
    virtual const char* filetype_string() const = 0 ;
    virtual void process_data() = 0 ;

    // open
        // const char* file_type_str = filetype_string() ;
        // use file_type_str to make file name
        // open the file

    // close
    // read

    // other stuff

struct customer_file : file_base
    virtual const char* filetype_string() const
    { return filetype ; }

    virtual void process_data() ;

    static const char* const filetype ;

    // other stuff

const char* const customer_file::filetype = "CUST" ;

---------- FOLLOW-UP ----------

QUESTION: Thank you Vijayan for your prompt reply.

I usually organize my constructors like this:

MyClass(<optional parameter1>, <optional parameter2>... <optional parameterN>)
  // so the constructor calls Initialize()
  Initialize((<optional parameter1>, <optional parameter2>... <optional parameterN>);

void Initialize(<optional parameter1>, <optional parameter2>... <optional parameterN>)
  // Initialize() sets the members.
  <optional parameter1> = <default value>;
  <optional parameter2> = <default value>;
  <optional parameterN> = <default value>;

this allows the same constructor to be called w/o parameters, and also allows to call Initialize() w/o parameters to perform cleanup after done with an object, before the destructor is called.

But initializing the constant string in a method wouldn't work from the constructor or Initialize() when called from the constructor... is that correct?

Is there any other way?

Thank you in advance,


> initializing the constant string in a method wouldn't work from the constructor or Initialize() when called from the constructor... is that correct?

yes. constants have to be initialized by the constructor.

Is there any other way?

you may be able to get the same effect by using a (non-const) pointer instead. eg.

struct A
     // the character sequence pointed to by const_string is a constant
     const char* const_string ; // the pointer itself is non-const

     A() { init() ; }

     explicit A( const char* cstr ) { init(cstr) ; }

     void init() { init( "default value" ) ; }
     void init( const char* cstr ) { const_string = cstr ; }

however, you have to make sure that the object pointed to (in this case the char sequence) has a life time which allows it to exist till the object is destroyed.  


All Answers

Answers by Expert:

Ask Experts




my primary areas of interest are generic and template metaprogramming, STL, algorithms, design patterns and c++11. i would not answer questions about gui and web programming.


about 15 years or so

post graduate engineer

©2017 All rights reserved.