Problem compiling C++/Arduino app that is using my derived class

I made a derived class called 'WebServer_My2KNJ.h' (see attached) from a working class called WebServer_My2.h (see attached) and I got the following error when I tried compiling the example program 'Web_HelloWorld.ino'.

The compile Error message: (or see the attached file 'ErrorMsg.txt'):

Web_HelloWorld.ino: In function 'void setup()':
Web_HelloWorld:57: error: invalid conversion from 'void (*)(WebServer_My2KNJ&, WebServer_My2::ConnectionType, char*, bool)' to 'void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)'
Web_HelloWorld:57: error: initializing argument 1 of 'void WebServer_My2::setDefaultCommand(void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool))'
Web_HelloWorld:61: error: invalid conversion from 'void (*)(WebServer_My2KNJ&, WebServer_My2::ConnectionType, char*, bool)' to 'void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)'
Web_HelloWorld:61: error: initializing argument 2 of 'void WebServer_My2::addCommand(const char*, void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool))'

The line 'webserver.setDefaultCommand(&helloCmd);' in the file 'Web_HelloWorld.ino' (see attached) is highlighted in the Arduino IDE as being responsible for the error.

Note:
(i) I am a Newbie to C++, so bear with me.
(ii) All files used except 'WebServer_My2KNJ.h' are basically the same found at 'https://github.com/sirleech/Webduino'.
(iii) In the parent class 'WebServer_My2.h', all I did was to modify 'WebServer.h' by changing 'private:' to 'protected:', and the class name.
(iv) 'Web_HelloWorld.ino' compiles and runs as expected if I use 'WebServer_My2.h' instead of 'WebServer_My2KNJ.h'.
(v) The reason I am going to this trouble, is that I want to later add more functionality to this class. Hence to keep things cleaner and simpler, it is best I have my code in a derived class.


Regards
Roger
ErrorMsg.txt
WebServer-My2.h
WebServer-My2KNJ.h
Web-HelloWorld.txt
Hope4UAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jkrCommented:
Consider this a shot in the dark (as I can't test it), but since you didn't change any behaviour of the implementation, a cast could fix that, e.g.

void setup()
{
  /* initialize the Ethernet adapter */
  Ethernet.begin(mac, ip);

  /* setup our default command that will be run when the user accesses
* the root page on the server */
  webserver.setDefaultCommand(static_cast<WebServer_My2>(&helloCmd));

  /* run the same command if you try to load /index.html, a common
* default page name */
  webserver.addCommand("index.html", static_cast<WebServer_My2>(&helloCmd));

  /* start the webserver */
  webserver.begin();
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
sarabandeCommented:
error: invalid conversion from 'void (*)(WebServer_My2KNJ&, WebServer_My2::ConnectionType, char*, bool)' to 'void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)'

the error means that the function pointer used in line 57 of Web_HelloWorld has not the prototype that was required. the first argument of your function was WebServer_My2KNJ& while the required argument type was WebServer_My2&. a function pointer cannot use inheritance on its arguments. so even if WebServer_My2KNJ is derived from class WebServer_My2 the function pointer argument could not be mapped and resolve that.

there are possibly 3 ways out:

- you may try the cast jkr has posted. he tries to cast the function pointer you provided to the required type.  it may work if WebServer_My2KNJ is derived directly from class WebServer_My2. it will not work if there is no inheritance between the classes or if multiple inheritance is involved.

- you may define the function as required. that means you change the first argument type from WebServer_My2KNJ& to WebServer_My2&. of course if you do so, and want to use the enhancements that your derived class has over the baseclass,  you have to virtually call into your derived class to using those enhancements in the function, cause the baseclass does not have access to those enhancements. note, you also could do a dynamic_cast on the argument but a virtual call always is the better choice before a cast.

- you may change the required function pointer type to taking a reference variable of your class rather than the WebServer_My2&. that could only work if you have the implementation (source code) of the function called _and_ if you want to replace the WebServer_My2 by your class.

the 3rd way is the only way if your class is not derived from WebServer_My2.

Sara
0
Hope4UAuthor Commented:
[1] The above threw new errors... see the attached.

[2] I have manage to gotten somewhere with the code with the help of a guru... it might be the solution: see http://stackoverflow.com/questions/19450497/c-and-arduino-cant-get-derived-webduino-class-to-work-compile-errors-with  I would have liked it that I wouldn't have to use the '#include WebServer_My2.h' in the main app 'Web-HelloWorld.ino'.  This stuff is complicated with trying to cast a pointer to a function... I was looking at overloading the functions 'webserver.setDefaultCommand(&helloCmd);', etc. the type def of 'Command(...)' to become:
typedef void Command(WebServer_My2KNJ &server, ConnectionType type,
                       char *url_tail, bool tail_complete);

but ended up with problems trying to cast the '*cmd' function pointer:

void WebServer_My2KNJ::setDefaultCommand(Command *cmd)
{
  m_defaultCmd = static_cast<WebServer_My2:Command>(cmd);  //<-- Got errors here
}
0
sarabandeCommented:
I would have liked it that I wouldn't have to use the '#include WebServer_My2.h' in the main app 'Web-HelloWorld.ino'.
 

if WebServer_My2KNJ is derived from WebServer_My2 then you need to include the WebServer_My2.h cause you need the class definition of your base class.

if WebServer_My2KNJ is a replacement of WebServer_My2, then  WebServer_My2KNJ.h should be used instead of WebServer_My2.h. additionally, you then need to replace all occurrences of WebServer_My2 in the WebServer_My2KNJ.h and all other source files.

m_defaultCmd = static_cast<WebServer_My2:Command>(cmd);  //<-- Got errors here

between WebServer_My2 and Command should be two colon characters :: . the member function should be a static function if using the typedef you got from the "guru" both in your class and in WebServer_My2. if it is not a static member function in WebServer_My2 then the function pointer actually is a pointer to member function what is one of the most complex and less flexible c++ concepts where you should keep off.

note, as told above, casting is the worse solution to your issue, especially if your goal is to replace the WebServer_My2 rather than to enhance it.

the simplest solution for you is to replace the WebServer_My2 by WebServer_My2KNJ at all places, thus removing all references to  WebServer_My2.
(and do no cast). instead define your overload of WebServer_My2KNJ::MyCommand as
 
void WebServer_My2KNJ::MyCommand(WebServer_My2 &server, ConnectionType type,
                     char *url_tail, bool tail_complete);

Open in new window



the second best solution is to derive from WebServer_My2 but don't change the typedef in
WebServer_My2.h and don't add a new typedef in your header.

with that, the statement

void WebServer_My2::setDefaultCmd(Command * cmd)
{
     m_defaultCmd = cmd; 
}

Open in new window

compiles and you would call such function from everywhere in WebServer_My2KNJ member functions by

this->setDefaultCmd(&WebServer_My2KNJ::MyCommand);

Open in new window


note, the this-> can be omitted in all non-static member functions of your class if you derive public from WebServer_My2.

Sara
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.