[comp.lang.c++] static member function for instance creation

delft@fwi.uva.nl (Andre van Delft) (10/28/90)

The Turbo C++ programmer's manual says:

  The main use of static members is to keep track of data common to all
  objects of a class, such as the number of objects created (...)

Thus a static member may be used for object creation (and I have a special
reason why I do not want a constructor). However its class cannot be
abstract, which I regret. I wanted 

class c {
  public:
    virtual void vf(int) = 0;
    static int n;
    static c* createOne() {n++; return new c;}  // NOT OK: c is abstract
}

class d:c {
  public:
    void vf(int) {}
}

void main() {
  d*anObject;
  anObject = d::createOne();
  ...
}

Am I overlooking something? Or should C++ permit the keyword "this" after 
the keyword "new", so that the following would be legal:

c* c::createOne() {n++; return new this;} // 'this' denotes the class!

Ok, I know I should use a constructor in such cases. I have a good reason to
want static members in abstract classes that make new instances:

I am currently working on a parallel extension to C++; this language,
Scriptic-C++, has simulation capabilities that are a bit comparable to
Simula. Scriptic offers a new, function-like refinement construct named
"script". For a shop simulation, a "customer" class with a generator in
Scriptic is:

class Customer {
  int birthtime;
public:
  static int n;
         int i;
  Customer(){i=n++;}

  scripts 
    Enter = {printf("customer %3u enters\n",i)}
    Leave = {printf("customer %3u leaves\n",i)}

    Live =     {birthtime=SimTime  }: Enter; GetServed(i);
          {qtime+=SimTime-birthtime}: Leave; {delete this}

   static scripts
     Poisson(t) = for(;;); {duration=RNDNEGEXP(t)}; {new Customer}->Live
};

...
scripts

  Day = Customer::Poisson(3) + HOURS(8) 
                        //  "+ HOURS(8)" kills script Poisson at closing time

This works fine. Note that I could not have taken a Customer constructor
in Day; I need a static member function for generating customers.

The problem arises when I want to generate other creatures as well
(thieves, mice, ...), WITHOUT reimplementing the static Poisson script for 
each kind of creature. (In Scriptic-C, without classes, this was possible
by passing a Customer script or something else as a parameter to a 
generic Poisson script: POISSON(3,Customer) ...)

In Scriptic-C++ I want to inherit from an abstract class, something like:

class Creature {
public:
  static int n;
         int i;
  Creature(){i=n++;}

  virtual scripts Live = 0;

   static scripts
     Poisson(t) = for(;;); {duration=RNDNEGEXP(t)}; {new this}->Live
};


class Customer: Creature {
  int birthtime;
public:
  scripts 
    Enter = {printf("customer %3u enters\n",i)}
    Leave = {printf("customer %3u leaves\n",i)}

    Live =     {birthtime=SimTime  }: Enter; GetServed(i);
          {qtime+=SimTime-birthtime}: Leave; {delete this}
};

class Thieve: Creature {
   ...
}

...
scripts

  Day = Customer::Poisson(3)
      + Thieve  ::Poisson(210)
      + Mouse   ::Poisson(120)
      + HOURS(8)


To summarize: I want the phrase "new this" permitted in static member
functions. I feel it would no be too hard to implement. Any comments?


Andre van Delft
DELFT@fwi.uva.nl

news@ux.acs.umn.edu (News) (11/01/90)

In article <1400@carol.fwi.uva.nl> delft@fwi.uva.nl (Andre van Delft) writes:
>The Turbo C++ programmer's manual says:
>
>  The main use of static members is to keep track of data common to all
>  objects of a class, such as the number of objects created (...)
>
>Thus a static member may be used for object creation (and I have a special
>reason why I do not want a constructor). However its class cannot be
>abstract, which I regret. I wanted 
>
>class c {
>  public:
>    virtual void vf(int) = 0;
>    static int n;
>    static c* createOne() {n++; return new c;}  // NOT OK: c is abstract
>}
>
>class d:c {
>  public:
>    void vf(int) {}
>}
>
>void main() {
>  d*anObject;
>  anObject = d::createOne();
>  ...
>}
>
>Am I overlooking something? Or should C++ permit the keyword "this" after 
>the keyword "new", so that the following would be legal:
>
>c* c::createOne() {n++; return new this;} // 'this' denotes the class!
>
>Ok, I know I should use a constructor in such cases. I have a good reason to
>want static members in abstract classes that make new instances:
>

	My solution to your problem would not be that. I had a similar
problem in which I had a number of different kinds of records on disk that I
wanted to read in, but they all had a few data items in common, and I wanted
to treat each record the same, no matter which type it was. I did something
like this:

class GMCRec : public Sortable {
   [data items]
public:
// All these are inherited from Sortable.
   virtual int OType() const;
   virtual int IsEqual() const;
   virtual int IsLessThan() const;
   virtual void PrintOn(ostream &) = 0;

// New ones for this class.
   virtual void GetFrom(istream &) = 0;
   virtual GMCRec *newone() = 0;

// Constructors....
   GMCRec() : [Data items initialized] {}
   GMCRec(GMCRec &other) : [Data items initialized] {}
   virtual ~GMCRec() {}
};

istream &operator >>(istream &in, GMCRec &rec)
{
   rec.GetFrom(in);
   return(in);
}

class SeafoodRec : public GMCRec {
   [extra data items]
public:
// From GMCRec.
   virtual int OType() const;
   virtual void PrintOn(ostream &);
   virtual void GetFrom(istream &);
   virtual GMCRec *newone();

// ........
};

GMCRec *SeafoodRec::newone()
{
   return new SeafoodRec();
}

	When I discovered what sort of records I was going to be reading for
this run, I made a master record that was a pointer to a record of the
proper type, and whenever I needed a new one to store another record in, I
made a call to master->newone() and got a record of the proper type. In my
opinion, your construct is unneccesary, at least not for the purpose which
you state.

Have fun,
UUCP: rutgers!umn-cs!donald.cs.umn.edu!hopper   (Eric Hopper)
     __                    /)                       /**********************/
    / ')                  //                         * I went insane to   *
   /  / ______  ____  o  //  __.  __  o ____. . _    * preserve my sanity *
  (__/ / / / <_/ / <_<__//__(_/|_/ (_<_(_) (_/_/_)_  * for later.         *
                       />                            * -- Ford Prefect    *
Internet:             </                            /**********************/
hopper@donald.cs.umn.edu
-- 
--
Nils_McCarthy mtymp01@ux.acs.umn.edu rutgers!umn-cs!ux.acs.umn.edu!mtymp01
"The wonders of modern technology..."
:-) :-) :-)