Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!uunet!timbuk!cs.umn.edu!ux.acs!news From: news@ux.acs.umn.edu (News) Newsgroups: comp.lang.c++ Subject: Re: static member function for instance creation Message-ID: <2614@ux.acs.umn.edu> Date: 1 Nov 90 02:30:20 GMT References: <1400@carol.fwi.uva.nl> Reply-To: hopper@donald.cs.umn.edu (Eric Hopper) Organization: Omnifarious Software Lines: 106 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: