PRODUCT : Borland C++ NUMBER : 1700 VERSION : All OS : All DATE : October 25, 1993 PAGE : 1/4 TITLE : Using BI_IArrayAsVector as a class data member /* ARRYADM.CPP: BI_IArrayAsVector as class data member This example illustrates the use of a template-based container class as a data member of another class. It also demonstrates the use of non-member functions pointers and the use of variable argument lists in a class constructor. The OPERATIONS class might be useful in creating a batch- like command executor. NOTES: (1) Tested with BC++ OS/2 1.0, BC++ 3.1 */ #include #include #include // All functions submitted to the OPS class constructor must // have a prototype that matches the following typedef. Editing // the following code line is all that is necessary to change // the function prototype expected by the OPS and OPERATIONS // classes. For instance: // typedef long (*AFUNC)(char*, char*); // would change the following code to expect a function that // returns a 'long' and takes two character pointers. Naturally // the example functions would have to be replaced with // functions whose signatures match. typedef int (*AFUNC)(void); //////////////////////////////////////////// OPS /////////////// // This class provides template container class compatible // function pointer objects. In this example, OPS objects are // passed to the constructor of an OPERATIONS class object and // are inserted into the OPERATIONS class object's ARRAY data // member. class OPS { public: OPS(const char *ids, const AFUNC af) { idString = new char[strlen(ids)+1]; strcpy(idString, ids); afunc = af; PRODUCT : Borland C++ NUMBER : 1700 VERSION : All OS : All DATE : October 25, 1993 PAGE : 2/4 TITLE : Using BI_IArrayAsVector as a class data member } ~OPS(void) { delete idString; } // Required by the BI_IArrayAsVector template int operator ==(const OPS&) const { return 0; } int isSortable(void) { return 0; } char *idString; AFUNC afunc; }; typedef OPS *POPS; typedef BI_IArrayAsVector ARRAY; //////////////////////////////////////////// OPERATIONS //////// // The OPERATIONS class is an example of a class which: // (1) uses variable argument lists in its constructor // (2) uses a template-based container class as a data // member. struct OPERATIONS { OPERATIONS(unsigned short slctd, ...) : operations(5, 0, 5), functions(0) { selected = slctd; va_list ap; POPS arg; va_start(ap, slctd); while((arg = va_arg(ap, POPS)) != 0) { operations.add(arg); ++functions; } va_end(ap); } void executeSelected(void) const { operations[selected]->afunc(); } char *selectedIs(void) const { return operations[selected]->idString; } void changeSelected(int i) { PRODUCT : Borland C++ NUMBER : 1700 VERSION : All OS : All DATE : October 25, 1993 PAGE : 3/4 TITLE : Using BI_IArrayAsVector as a class data member selected = i; } operator int() { return functions; } private: ARRAY operations; int selected; int functions; }; typedef OPERATIONS *POPERATIONS; // Some gutless demo functions with the required prototype //-------------------------------------------------------------- int nop(void) { cout << "\nDoing nothing!"; return 0; } //-------------------------------------------------------------- int deleteFile(void) { cout << "\nDeleting file!"; return 0; } //-------------------------------------------------------------- int renameFile(void) { cout << "\nRenaming file!"; return 0; } //-------------------------------------------------------------- int copyFile(void) { cout << "\nCopying file!"; return 0; } //************************************************************** void main(void) { // Install our functions and function descriptions into // OPS objects. PRODUCT : Borland C++ NUMBER : 1700 VERSION : All OS : All DATE : October 25, 1993 PAGE : 4/4 TITLE : Using BI_IArrayAsVector as a class data member POPS op1 = new OPS("NULL function", nop); POPS op2 = new OPS("Copy file", copyFile); POPS op3 = new OPS("Delete file", deleteFile); POPS op4 = new OPS("Rename file", renameFile); // First argument in the creation of an OPERATIONS object is // the array indici of the function to be initialially // selected. The last argument is always 0. In between is the // variable list of OPS objects. // NOTE!!! The OPERATIONS class expects these objects to have // been dynamically allocated. If they are local, static or // global objects, this program will crash!!!! If static, local // or global objects must be used, the OPERATIONS class will // have to be modified to support a TShouldDelete::NoDelete // facility. OPERATIONS operations(2, op1, op2, op3, op4, 0L); // Lets see if initial function selection went as planned. cout << "Initial selected function is " << operations.selectedIs(); operations.executeSelected(); // Note that the OPERATIONS class member function // "operator int()" makes this particular for-loop // work. for (int i = 0; i < operations; i++) { operations.changeSelected(i); operations.executeSelected(); } } // end of main() DISCLAIMER: You have the right to use this technical information subject to the terms of the No-Nonsense License Statement that you received with the Borland product to which this information pertains.