0

我创建了一个名为WebServer_My2KNJ.h工作类的派生类WebServer_My2.h(有关这些文件的详细信息,请参见下面的注释部分),当我尝试编译示例程序时出现以下错误Web_HelloWorld.ino::

编译错误信息:(或查看附件'ErrorMsg.txt'):

Web_HelloWorld.ino:在函数“无效设置()”中:
Web_HelloWorld:57:错误:从 'void (*)(WebServer_My2KNJ&, WebServer_My2::ConnectionType, char*, bool)' 到 'void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)' 的无效转换
Web_HelloWorld:57: 错误: 初始化参数 1'void WebServer_My2::setDefaultCommand(void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool))'
Web_HelloWorld:61:错误:从 'void (*)(WebServer_My2KNJ&, WebServer_My2::ConnectionType, char*, bool)' 到 'void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)' 的无效转换
Web_HelloWorld:61:错误:初始化 'void WebServer_My2::addCommand(const char*, void (*)(WebServer_My2&, WebServer_My2::ConnectionType, char*, bool)) 的参数 2

webserver.setDefaultCommand(&helloCmd);文件中的行Web_HelloWorld.ino此时突出显示。

我的派生类:

/*
  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

笔记:

  1. 我是 C++ 的新手,所以请耐心等待。
  2. 除了“WebServer_My2KNJ.h”之外,所有使用的文件都与“ https://github.com/sirleech/Webduino ”中的基本相同。
  3. 如果我使用“WebServer_My2.h”而不是“WebServer_My2KNJ.h”,“Web_HelloWorld.ino”编译并运行良好。
  4. 在父类“WebServer_My2.h”中,我所做的只是通过将“private:”更改为“protected:”和类名来修改“WebServer.h”。
  5. 我遇到这个麻烦的原因是我想稍后为这个类添加更多功能。因此,为了使事情更简洁,最好将我的代码放在派生类中。
4

1 回答 1

0

简短的回答:

改为helloCmd()采取 aWebServer_My2&而不是 a WebServer_My2KNJ&

长答案:

看起来问题源于文件Command中的函数指针 typedef WebServer_My2.h。它大概声明如下(第~169行):

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

这意味着它是一个指向函数的指针,该函数接受对WebServer_My2对象的引用作为其第一个参数(后面是其他一些参数)。有一些方法,例如setDefaultCommand(),接受这种精确类型的函数指针。C++ 在这里很严格。您不能替换另一个接受派生类型的引用参数的函数指针。

我知道您说您没有 modify helloCmd,但是根据错误消息,我不得不假设您实际上将参数列表更改为:

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

因此,当代码尝试执行这些行时,问题就来了:

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

setDefaultCommand()andaddCommand()方法需要一个函数指针,它将WebServer_My2引用作为其第一个参数。但是,helloCmd()实际上需要WebServer_My2KNJ参考。这是行不通的,因为类型不同(即使一个是从另一个派生的)。

一个快速的解决方案是helloCmd()按照我在上面简短答案中的建议进行更改。这样,它至少应该能够编译和运行示例。如果您想使用添加到子类的扩展功能,则可以在函数中执行此操作:

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

然后,您可以使用myServer指针访问所有添加的网络服务器功能。请记住,它是一个指针,因此您需要使用->运算符而不是.运算符来访问成员。

如果可能,dynamic_cast将向下转换继承层次结构。如果转换不起作用,它将返回一个空指针 (0),这就是该if ()块是必要的原因。

于 2013-10-18T17:51:53.560 回答