home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #26 / NN_1992_26.iso / spool / comp / lang / cplus / 16041 < prev    next >
Encoding:
Text File  |  1992-11-10  |  3.8 KB  |  130 lines

  1. Newsgroups: comp.lang.c++
  2. Path: sparky!uunet!utcsri!torn!nott!bnrgate!bmerh85!bnr.ca!glenm
  3. From: glenm@bnr.ca (Glen Martin)
  4. Subject: Re: Discriminating Variant Records Without switch() ??
  5. Message-ID: <1992Nov10.181529.2711@bmerh85.bnr.ca>
  6. Sender: news@bmerh85.bnr.ca (Usenet News)
  7. Reply-To: glenm@bnr.ca
  8. Organization: Bell-Northern Research Ltd.
  9. References:  <BAB.92Nov10073324@se39.wg2.waii.com>
  10. Date: Tue, 10 Nov 92 18:15:29 GMT
  11. Lines: 117
  12.  
  13. In article <BAB.92Nov10073324@se39.wg2.waii.com>, bab@se39.wg2.waii.com (Brian Button) writes:
  14. ...
  15. |> As an example:
  16. |> 
  17. |> We're reading structures sent to us over a socket. Since these
  18. |> structures are being sent and received on the same machine, we can
  19. |> just memcpy the byte stream read from the socket into a big union, and
  20. |> then switch based on the first field of the union to determine the type.
  21. |> 
  22. |> As a trivial example:
  23. |> 
  24. |> {
  25. |>     read( sd, buf, 16 );
  26. |>     memcpy(( char * )&union_of_structs, buf, 16 );
  27. |>     switch( union_of_structs.type )
  28. |>     {
  29. |>         case A:
  30. |> 
  31. |>             .
  32. |>             .
  33. |>             .
  34. |>     }
  35. |> }
  36.  
  37. Well, this is a bit of a can of worms.
  38.  
  39. It seems reasonable to use subclassing and virtual functions to
  40. take the place of the switch. Sadly, that leaves us with the
  41. problem of creating different classes depending on the data
  42. read.
  43.  
  44. It would seem to me that a solution to this problem would be a
  45. class dispatcher (or whatever you'd like to call it). Basically,
  46. the central entity is responsible for creating objects based on
  47. the data stream, having been given a list of tags and constructors
  48. to use for this purpose.
  49.  
  50. Below is a skeleton of the idea. There are a lot of details I
  51. haven't bothered with, but I hope this gives you the basic idea.
  52. The benefit of an approach like this is that it avoids the case
  53. statement, which is bad largely because of its hard-coded nature.
  54. If I want to create a new class, all I need to do is inherit from
  55. streamclass, implement the read and perform functions, and I'm
  56. done.
  57.  
  58. The remaining hard-coded detail is the tags - somehow the two sides
  59. of the pipe must agree on the tag values for each class. Maybe an
  60. incrementing counter based on order of registration? Sounds icky.
  61. Maybe the text of the class name? This area needs work still. It
  62. would probably be best if the two sides could share the dispatch
  63. and class code, as well as the static object declarations. Basically,
  64. all of the following example except the main function. This would go
  65. a long way toward assuring tag consistency.
  66.  
  67.  
  68. class streamclass {
  69.   public:
  70.     virtual perform() = 0;
  71.     virtual read() = 0;
  72. };
  73.  
  74. class dispatch {
  75.   public:
  76.     register( tag, streamclass * );   // insert tag & pointer into table
  77.     streamclass *read();
  78.     dispatch() { num = 0; }
  79.   private:
  80.     int num;
  81.     struct table_s {
  82.       int tag;
  83.       stramclass *staticObj;
  84.     } table[MAXOBJS];
  85. }
  86.  
  87. streamclass *dispatch::read() {
  88.   struct table_s *tableEntry;
  89.   streamclass *obj;
  90.  
  91.   // read a tag
  92.   tag = ...
  93.  
  94.   // look up in table, find the entry
  95.   tableEntry = ...
  96.  
  97.   obj = tableEntry->staticObj->read();
  98.   return(obj);
  99. }
  100.  
  101. class foo : public streamclass {
  102.   public:
  103.     foo() { register( <some unique tag value>, this ); }
  104.     foo *read();             // build an object from the input stream
  105.     void perform();
  106. }
  107.  
  108. dispatch theDisplatcher;
  109. foo      staticFoo;       // this is created just as something for
  110.                           // theDispatcher to call a read function on.
  111.  
  112.  
  113. void main()
  114. {
  115.   .
  116.   .
  117.   .
  118.   streamclass *s;
  119.   s = theDispatcher.read();
  120.   s->perform();
  121.   .
  122.   .
  123.   .
  124. }
  125.  
  126. --------------------------------------------------------------------------------
  127. Glen Martin              Bell-Northern Research          Ottawa, Ontario, Canada
  128. Phone : (613) 763-7299   Fax: (613) 763-2626             Internet: glenm@bnr.ca
  129. --------------------------------------------------------------------------------
  130.