home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.c++
- Path: sparky!uunet!utcsri!torn!nott!bnrgate!bmerh85!bnr.ca!glenm
- From: glenm@bnr.ca (Glen Martin)
- Subject: Re: Discriminating Variant Records Without switch() ??
- Message-ID: <1992Nov10.181529.2711@bmerh85.bnr.ca>
- Sender: news@bmerh85.bnr.ca (Usenet News)
- Reply-To: glenm@bnr.ca
- Organization: Bell-Northern Research Ltd.
- References: <BAB.92Nov10073324@se39.wg2.waii.com>
- Date: Tue, 10 Nov 92 18:15:29 GMT
- Lines: 117
-
- In article <BAB.92Nov10073324@se39.wg2.waii.com>, bab@se39.wg2.waii.com (Brian Button) writes:
- ...
- |> As an example:
- |>
- |> We're reading structures sent to us over a socket. Since these
- |> structures are being sent and received on the same machine, we can
- |> just memcpy the byte stream read from the socket into a big union, and
- |> then switch based on the first field of the union to determine the type.
- |>
- |> As a trivial example:
- |>
- |> {
- |> read( sd, buf, 16 );
- |> memcpy(( char * )&union_of_structs, buf, 16 );
- |> switch( union_of_structs.type )
- |> {
- |> case A:
- |>
- |> .
- |> .
- |> .
- |> }
- |> }
-
- Well, this is a bit of a can of worms.
-
- It seems reasonable to use subclassing and virtual functions to
- take the place of the switch. Sadly, that leaves us with the
- problem of creating different classes depending on the data
- read.
-
- It would seem to me that a solution to this problem would be a
- class dispatcher (or whatever you'd like to call it). Basically,
- the central entity is responsible for creating objects based on
- the data stream, having been given a list of tags and constructors
- to use for this purpose.
-
- Below is a skeleton of the idea. There are a lot of details I
- haven't bothered with, but I hope this gives you the basic idea.
- The benefit of an approach like this is that it avoids the case
- statement, which is bad largely because of its hard-coded nature.
- If I want to create a new class, all I need to do is inherit from
- streamclass, implement the read and perform functions, and I'm
- done.
-
- The remaining hard-coded detail is the tags - somehow the two sides
- of the pipe must agree on the tag values for each class. Maybe an
- incrementing counter based on order of registration? Sounds icky.
- Maybe the text of the class name? This area needs work still. It
- would probably be best if the two sides could share the dispatch
- and class code, as well as the static object declarations. Basically,
- all of the following example except the main function. This would go
- a long way toward assuring tag consistency.
-
-
- class streamclass {
- public:
- virtual perform() = 0;
- virtual read() = 0;
- };
-
- class dispatch {
- public:
- register( tag, streamclass * ); // insert tag & pointer into table
- streamclass *read();
- dispatch() { num = 0; }
- private:
- int num;
- struct table_s {
- int tag;
- stramclass *staticObj;
- } table[MAXOBJS];
- }
-
- streamclass *dispatch::read() {
- struct table_s *tableEntry;
- streamclass *obj;
-
- // read a tag
- tag = ...
-
- // look up in table, find the entry
- tableEntry = ...
-
- obj = tableEntry->staticObj->read();
- return(obj);
- }
-
- class foo : public streamclass {
- public:
- foo() { register( <some unique tag value>, this ); }
- foo *read(); // build an object from the input stream
- void perform();
- }
-
- dispatch theDisplatcher;
- foo staticFoo; // this is created just as something for
- // theDispatcher to call a read function on.
-
-
- void main()
- {
- .
- .
- .
- streamclass *s;
- s = theDispatcher.read();
- s->perform();
- .
- .
- .
- }
-
- --------------------------------------------------------------------------------
- Glen Martin Bell-Northern Research Ottawa, Ontario, Canada
- Phone : (613) 763-7299 Fax: (613) 763-2626 Internet: glenm@bnr.ca
- --------------------------------------------------------------------------------
-