c++ - Refactor code that violates "Needless Repition" principle -


assume class animal eat, sleep , make noise. assume class mammal : public animal makesbaby assume mammal eat, sleep , make noise inherits animal. 

this code extended code presented in this question answered yesterday dan masek.

the problems code are:

  1. mammal can't inherit animal (compile error)
  2. mammal cannot eat, sleep or make noise
  3. code suffers "needless repetition", meeting scorn , derision of uncle bob martin.

i want code excellent possible, stuck.

i think similarities between 2 classes center around typedef defines function pointer member in class. tried templating this, ran numerous compile errors, demonstrating utter failure comprehend how solve problem. hence post.

for saw previous post, have added #ifdef disable printing (this arduino code, std not available), , added asserts wherever could. added mammal class.

//  set false suppress serial.print output #define tracing true class animal { public:     enum {         cmd_eat = 1         , cmd_sleep         , cmd_makenoise         , command_count     };      //  define pointer function within class takes     //  int argument     typedef void(animal::*animalfunc)(int); // u thing problem - can templated? if so, not figure out syntax make work      struct commandinfo     {         unsigned int code;         animalfunc handler;         char const* name;     };      animal(char const* name) : _name(name) {         registercommands();     }      //  register commands supported class     virtual void registercommands() { #if tracing         serial.print(f("registering "));         serial.print(getname());         serial.println(f(" actions:")); #endif         unsigned int index = 0;         registercommand(index++, cmd_eat, "eat", &animal::eat);         registercommand(index++, cmd_sleep, "sleep", &animal::sleep);         registercommand(index++, cmd_makenoise, "make noise", &animal::makenoise);          assert(index == 3);     }      //  register using index rather code don't overload meaning of code.     void registercommand(unsigned int index, unsigned int code, char const* action, animalfunc fn) {         assert(code < command_count);         _commands[index].code = code;         _commands[index].name = action;         _commands[index].handler = fn; #if tracing         serial.print( "registering: index=");         serial.print(index);         serial.print(f(", code="));         serial.print(_commands[index].code);         serial.print(f(", action="));         serial.println(_commands[index].name); #endif     }      void report(unsigned int code, char const* msg) {         commandinfo info = getcommandinfo(code); #if tracing         serial.print(msg);         serial.print(info.code);         serial.print(" [");         serial.print(info.name);         serial.println("]"); #endif     }      void exec(int code, int value) {         commandinfo info = getcommandinfo(code); #if tracing         report(code, "executing: "); #endif         (this->*info.handler)(value);     }      char const* getname() {         return _name;     }      //  base class methods     virtual void eat(int times) {         while (times-- > 0) {             reportdofunc(cmd_eat);         }     }      virtual void sleep(int times) {         while (times-- > 0) {             reportdofunc(cmd_sleep);         }     }      virtual void makenoise(int times) {         while (times-- > 0) {             reportdofunc(cmd_makenoise);         }     }      virtual void showactions() { #if tracing         serial.print(getname());         serial.print(f(" implements "));         serial.print(command_count);         serial.println(f(" actions:"));         (int = 0; < command_count; i++) {             showaction(i);         } #endif     }      void showaction(unsigned int index) { #if tracing         serial.print(f("index: ["));         serial.print(index);         serial.print(f("] code: ["));         serial.print(_commands[index].code);         serial.print(f("] "));         serial.println(_commands[index].name); #endif     }  private:     char const* _name;      //  define array of pointers action functions     commandinfo _commands[command_count];      //  return command associated code     commandinfo getcommandinfo(unsigned int code) { #if tracing         serial.print(f("in getcommandinfo: code="));         serial.print(code);         serial.println(f(":")); #endif         (int = 0; < command_count; i++) { #if tracing             serial.print(f("checking index: ["));             serial.print(i);             serial.print(f("], code: ["));             serial.print(_commands[i].code); #endif             if (code == _commands[i].code) { #if tracing                 serial.print(f("] found "));                 serial.println(_commands[i].name); #endif                 return _commands[i];             } #if tracing             serial.println("]"); #endif         }          //  invalid command code object         assert(false);     }      void reportdofunc(unsigned int code) {         commandinfo info = getcommandinfo(code); #if tracing         serial.print(code);         serial.print(f(": "));         serial.println(info.name); #endif     }  };  //class mammal : public animal {    <-- form fails: "no matching function call animal::animal() class mammal {     public:     enum {         cmd_births_baby = 1,         command_count     };      typedef void(mammal::*mammalfunc)(int);     // <-- difference animalfunc class name      struct commandinfo {         unsigned int code;         char const* name;         mammalfunc handler;                 // <-- difference parent class mammalfunc     };      //  constructor     mammal(char const* name) : _name(name) {    // <-- identical parent (animal) class          registercommands();     }      //  register commands supported class     virtual void registercommands() { #if tracing         serial.print(f("registering "));         serial.print(getname());         serial.println(f(" actions:")); #endif          //  can list abstracted table register command can inherit?         unsigned int index = 0;         registercommand(index++, cmd_births_baby, "births baby", &mammal::birthsbaby);     }      //  difference animal::registercommand last argument (mannalfunc instead of animalfunc)     void registercommand(unsigned int index, unsigned int code, char const* action, mammalfunc fn) {          //  assure don't have more commands thought...         assert(index < command_count);          //  update values of current placeholder struct's values         _commands[index].code = code;         _commands[index].name = action;         _commands[index].handler = fn;  #if tracing         report(code, "registering: "); #endif     }      //  identical animal::exec     void exec(int code, int value) {         commandinfo info = getcommandinfo(code); #if tracing         report(code, "executing: "); #endif         (this->*info.handler)(value);     }      //  identical animal::report     void report(unsigned int code, char const* msg) {         commandinfo info = getcommandinfo(code); #if tracing         serial.print(msg);         serial.print(info.code);         serial.print(" [");         serial.print(info.name);         serial.println("]"); #endif     }      //  identical animal::getname     char const* getname() {         return _name;     }      //  identical animal::showactions     virtual void showactions() { #if tracing         serial.print(getname());         serial.print(f(" implements "));         serial.print(command_count);         serial.println(f(" actions:"));         (int = 0; < command_count; i++) {             showaction(i);         } #endif     }      //  identical animal::showaction     void showaction(unsigned int index) {         assert(index < command_count);  #if tracing         serial.print(f("["));         serial.print(_commands[index].code);         serial.print(f("] "));         serial.println(_commands[index].name); #endif     }      //  concrete action     virtual void birthsbaby(int times) {         while (times-- > 0) {             reportdofunc(cmd_births_baby);         }     }  private:      //  inherit?     char const* _name;      //  commandinfo mammal-specific. can generic?     //  define array of pointers action functions     commandinfo _commands[command_count];      commandinfo getcommandinfo(unsigned int code) { #if tracing         serial.print(f("in getcommandinfo: code="));         serial.print(code);         serial.println(f(":")); #endif         (int = 0; < command_count; i++) { #if tracing             serial.print(f("checking index: ["));             serial.print(i);             serial.print(f("], code: ["));             serial.print(_commands[i].code); #endif             if (code == _commands[i].code) { #if tracing                 serial.print(f("] found "));                 serial.println(_commands[i].name); #endif                 return _commands[i];             } #if tracing             serial.println(f("]")); #endif         }          //  invalid command code object         assert(false);     }      //  identical animal::reportdofunc     void reportdofunc(unsigned int code) {         commandinfo info = getcommandinfo(code); #if tracing         serial.print(code);         serial.print(f(": "));         serial.println(info.name); #endif     }  };  int main() {     animal *panimal = new animal("animal");     panimal->exec(animal::cmd_eat, 1);     panimal->exec(animal::cmd_sleep, 1);     panimal->exec(animal::cmd_makenoise, 2);     panimal->showactions();      mammal* pmammal = new mammal("mammal");     pmammal->exec(mammal::cmd_births_baby, 2);     pmammal->showactions();     pmammal->exec(animal::cmd_eat, 2);      delete pmammal;     delete panimal; } 


Comments

Popular posts from this blog

ios - RestKit 0.20 — CoreData: error: Failed to call designated initializer on NSManagedObject class (again) -

laravel - PDOException in Connector.php line 55: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) -

java - Digest auth with Spring Security using javaconfig -