Pergunta

I made a derived class called WebServer_My2KNJ.h of a working class called WebServer_My2.h (see Note section below for details on these files) 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 is highlighted at the time.

My Derived Class:

/*
  WebServer_My2KNJ.cpp - Extension of the library class 'WebServer_My2'
  Created by: COG008
  Date Created: 2013/10/17
*/

#ifndef WebServer_My2KNJ_h
#define WebServer_My2KNJ_h

#include <..\Webduino_My2\WebServer_My2.h>

class WebServer_My2KNJ: public WebServer_My2
{
public:

// constructor for webserver object
WebServer_My2KNJ(const char *p_urlPrefix = "", int p_port = 80); 
};
WebServer_My2KNJ::WebServer_My2KNJ(const char *p_urlPrefix, int p_port) : 
WebServer_My2::WebServer_My2(p_urlPrefix, p_port)
{
;
}

#endif

Note:

  1. I am a Newbie to C++, so bear with me.
  2. All files used except 'WebServer_My2KNJ.h' are basically the same found at 'https://github.com/sirleech/Webduino'.
  3. 'Web_HelloWorld.ino' compiles and runs fine if I use 'WebServer_My2.h' instead of 'WebServer_My2KNJ.h'.
  4. In the parent class 'WebServer_My2.h', all I did was to modify 'WebServer.h' by changing 'private:' to 'protected:', and the class name.
  5. 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.
Foi útil?

Solução

Short answer:

Change helloCmd() to take a WebServer_My2& instead of a WebServer_My2KNJ&.

Long answer:

It looks like the problem stems from the Command function pointer typedef in your WebServer_My2.h file. It's presumably declared as follows (line ~169):

typedef void Command(WebServer_My2 &server, ConnectionType type,
                     char *url_tail, bool tail_complete);

That means it's a pointer to a function which accepts a reference to a WebServer_My2 object as its first parameter (followed by some others). There are some methods, such as setDefaultCommand(), which accept function pointers of this exact type. C++ is strict here. You can't substitute another function pointer which accepts reference parameters of a derived type.

I know you said you didn't modify helloCmd, but based on the error message, I have to assume you actually changed the parameter list to this:

void helloCmd(WebServer_My2KNJ &server, WebServer_My2::ConnectionType type, char *, bool)

The problem therefore comes when the code tries to do these lines:

webserver.setDefaultCommand(&helloCmd);
webserver.addCommand("index.html", &helloCmd);

The setDefaultCommand() and addCommand() methods are expecting a function pointer which takes a WebServer_My2 reference as its first parameter. However, helloCmd() actually takes a WebServer_My2KNJ reference. That won't work because the types are different (even though one is derived from the other).

A quick solution is to change helloCmd() as I suggested in the short answer above. That way it should at least be able to compile and run the example. If you want to use the extended functionality that you added to your subclass, then you can do this in the function:

WebServer_My2KNJ * myServer = dynamic_cast<WebServer_My2KNJ*>(&server);
if (myServer) {
    // myServer is safe to use here
}

You can then use the myServer pointer to access all your added webserver functionality. Just remember that it's a pointer though, so you need to use the -> operator instead of the . operator to access members.

The dynamic_cast converts down the inheritance hierarchy if possible. It returns a null pointer (0) if the conversion doesn't work, which is why the if () block is necessary.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top