65

我从下载的示例中获取了以下代码片段:

bool ChatServer::event(QEvent * event)
{
    if(event->type() == QEvent::User)
    {
        UserEvent * ue = static_cast<UserEvent *>(event);
        switch(ue->userType)
        {
            case CR::ErrorEvent:
            case CR::LogEvent:
            {   
                TraceEvent * te = static_cast<TraceEvent *>(ue);
                if(te->userType == CR::ErrorEvent)
                {
                    error(te->msg);
                }
                else
                {
                    log(te->msg);
                }
            }
                break;
            default:
                return false;
        }
    }
    else
    {
        return QTcpServer::event(event);
    }
    return true;
}

现在如果编译程序我得到这个错误:

g++ -c -pipe -O2 -Wall -W -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/share/qt4/mkspecs/freebsd-g++ -I. -I/usr/local/include/qt4/QtCore -I/usr/local/include/qt4/QtNetwork -I/usr/local/include/qt4 -I. -I/usr/local/include/qt4 -I/usr/local/include -o chatserver.o chatserver.cpp
g++ -c -pipe -O2 -Wall -W -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/share/qt4/mkspecs/freebsd-g++ -I. -I/usr/local/include/qt4/QtCore -I/usr/local/include/qt4/QtNetwork -I/usr/local/include/qt4 -I. -I/usr/local/include/qt4 -I/usr/local/include -o clientservice.o clientservice.cpp
clientservice.cpp: In member function 'virtual bool ClientService::event(QEvent*)':
clientservice.cpp:37: error: jump to case label
clientservice.cpp:34: error:   crosses initialization of 'MessageEvent* me'
clientservice.cpp:41: error: jump to case label
clientservice.cpp:38: error:   crosses initialization of 'UserInfoEvent* uie'
clientservice.cpp:34: error:   crosses initialization of 'MessageEvent* me'
clientservice.cpp:44: error: jump to case label
clientservice.cpp:38: error:   crosses initialization of 'UserInfoEvent* uie'
clientservice.cpp:34: error:   crosses initialization of 'MessageEvent* me'
clientservice.cpp:31: warning: enumeration value 'EventTypeBegin' not handled in switch
clientservice.cpp:31: warning: enumeration value 'LogEvent' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ErrorEvent' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ClientConnected' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ClientReg' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ClientDisconnect' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ServerConnected' not handled in switch
clientservice.cpp:31: warning: enumeration value 'ServerDisconnect' not handled in switch
clientservice.cpp:31: warning: enumeration value 'DoConnect' not handled in switch
clientservice.cpp:31: warning: enumeration value 'DoDisconnect' not handled in switch
clientservice.cpp:31: warning: enumeration value 'GotMessage' not handled in switch
clientservice.cpp:31: warning: enumeration value 'GotUserInfo' not handled in switch
clientservice.cpp:31: warning: enumeration value 'SendUserInfo' not handled in switch
clientservice.cpp:31: warning: enumeration value 'GotClientInfo' not handled in switch
clientservice.cpp:31: warning: enumeration value 'SendClientInfo' not handled in switch
clientservice.cpp:31: warning: enumeration value 'EventTypeEnd' not handled in switch
clientservice.cpp: In member function 'void ClientService::readClient()':
clientservice.cpp:63: warning: comparison between signed and unsigned integer expressions
clientservice.cpp:87: error: jump to case label
clientservice.cpp:83: error:   crosses initialization of 'Message* msg'
clientservice.cpp:92: error: jump to case label
clientservice.cpp:88: error:   crosses initialization of 'UserInfo* ui'
clientservice.cpp:83: error:   crosses initialization of 'Message* msg'
clientservice.cpp:97: error: jump to case label
clientservice.cpp:93: error:   crosses initialization of 'ClientInfo* ci'
clientservice.cpp:88: error:   crosses initialization of 'UserInfo* ui'
clientservice.cpp:83: error:   crosses initialization of 'Message* msg'
clientservice.cpp: In member function 'bool ClientService::sendToClient(CR::MsgType::MsgType, SendAble*)':
clientservice.cpp:124: warning: comparison of unsigned expression < 0 is always false
clientservice.cpp: In member function 'void ClientService::gotUserInfo(UserInfo*)':
clientservice.cpp:176: error: cast from 'ClientService*' to 'quint32' loses precision
*** Error code 1

Stop in ~/SimpleChatRoomServer

现在,如果删除case语句的括号,我会收到此错误:

g++ -c -pipe -O2 -Wall -W -DQT_NO_DEBUG -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/share/qt4/mkspecs/freebsd-g++ -I. -I/usr/local/include/qt4/QtCore -I/usr/local/include/qt4/QtNetwork -I/usr/local/include/qt4 -I. -I/usr/local/include/qt4 -I/usr/local/include -o chatserver.o chatserver.cpp
chatserver.cpp: In member function 'virtual bool ChatServer::event(QEvent*)':
chatserver.cpp:108: error: jump to case label
chatserver.cpp:98: error:   crosses initialization of 'TraceEvent* te'
chatserver.cpp:94: warning: enumeration value 'EventTypeBegin' not handled in switch
chatserver.cpp:94: warning: enumeration value 'ClientConnected' not handled in switch
chatserver.cpp:94: warning: enumeration value 'ClientReg' not handled in switch
chatserver.cpp:94: warning: enumeration value 'ClientDisconnect' not handled in switch
chatserver.cpp:94: warning: enumeration value 'ServerConnected' not handled in switch
chatserver.cpp:94: warning: enumeration value 'ServerDisconnect' not handled in switch
chatserver.cpp:94: warning: enumeration value 'DoConnect' not handled in switch
chatserver.cpp:94: warning: enumeration value 'DoDisconnect' not handled in switch
chatserver.cpp:94: warning: enumeration value 'GotMessage' not handled in switch
chatserver.cpp:94: warning: enumeration value 'SendMessage' not handled in switch
chatserver.cpp:94: warning: enumeration value 'GotUserInfo' not handled in switch
chatserver.cpp:94: warning: enumeration value 'SendUserInfo' not handled in switch
chatserver.cpp:94: warning: enumeration value 'GotClientInfo' not handled in switch
chatserver.cpp:94: warning: enumeration value 'SendClientInfo' not handled in switch
chatserver.cpp:94: warning: enumeration value 'EventTypeEnd' not handled in switch
*** Error code 1

Stop in ~/SimpleChatRoomServer.

的完整源代码SimpleChatRoomServer.cpp

#include <QTextStream>
#include <QDateTime>
#include "traceevent.h"
#include "chatserver.h"
#include "chatcenterthread.h"
#include "clientservicethread.h"
#include "message.h"
#include "server.h"

ChatServer::ChatServer(QObject * parent)
        :QTcpServer(parent)
{
    QFile * inFile = new QFile(this);
    QFile * outFile = new QFile(this);
    QFile * errFile = new QFile(this);
    inFile->open(stdin,QIODevice::ReadOnly);
    outFile->open(stdout,QIODevice::WriteOnly);
    errFile->open(stderr,QIODevice::WriteOnly);
    setIO(inFile,outFile,errFile);

    qobject_cast<Server *>(qApp)->csrId = this;
    csrId = (QObject *)(0+CR::ServerId);
}

ChatServer::~ChatServer()
{
    for(int i = 0; i < ccs.size(); i++)
    {
        ccs.at(i)->deleteLater();
    }
}

void ChatServer::setIO(QFile * inFile,QFile * outFile,QFile * errFile)
{
    in.setDevice(inFile);
    out.setDevice(outFile);
    err.setDevice(errFile);
}

void ChatServer::incomingConnection(int socketId)
{
    ClientServiceThread *cst = new ClientServiceThread(socketId,this);
    cst->start();
    connect(cst,SIGNAL(finished()),cst,SLOT(deleteLater()));
}

bool ChatServer::init(quint16 & port)
{
    if(!port)
    {
        bool ok = false;
        while(!ok)
        {
            out<<tr("Port[5555]: ");
            out.flush();
            QString p;
            p = in.read(1);
            if(p!=QString("\n"))
            {
                QString strport;
                strport = in.readLine(10);
                strport = p + strport;
                port = strport.toUInt(&ok);
            }
            else
            {
                port = 5555;
                ok = true;
            }
        }
    }

    //ADD ONE ChatCenter
    ChatCenterThread * cct = new ChatCenterThread(this);
    cct->start();
    connect(cct,SIGNAL(finished()),cct,SLOT(deleteLater()));

    if(!listen(QHostAddress::Any,port))
    {
        error(tr("Listen at [%1] fail!").arg(port));
        deleteLater();
        exit(1);
        return false;
    }
    log(tr("Listen at [%1]").arg(port));
    return true;
}

bool ChatServer::event(QEvent * event)
{
    if(event->type() == QEvent::User)
    {
        UserEvent * ue = static_cast<UserEvent *>(event);
        switch(ue->userType)
        {
            case CR::ErrorEvent:
            case CR::LogEvent:
                TraceEvent * te = static_cast<TraceEvent *>(ue);
                if(te->userType == CR::ErrorEvent)
                {
                    error(te->msg);
                }
                else
                {
                    log(te->msg);
                }
                break;
            default:
                return false;
        }
    }
    else
    {
        return QTcpServer::event(event);
    }
    return true;
}

void ChatServer::error(QString msg)
{
    err<<QDateTime::currentDateTime().toString(Qt::ISODate)
            <<" !ERROR! "<<msg<<endl;
}

void ChatServer::log(QString msg)
{
    out<<QDateTime::currentDateTime().toString(Qt::ISODate)
            <<" "<<msg<<endl;
}

1)我是否错误地使用了括号?

2)为什么在case语句中使用括号显示crosses initialization给其他代码行。

4

2 回答 2

141

C++ 标准说:

可以转移到一个块中,但不能通过初始化绕过声明的方式。从具有自动存储持续时间的局部变量不在范围内的点跳转到它在范围内的点的程序是格式错误的,除非该变量具有 POD 类型 (3.9) 并且在没有初始化程序的情况下声明。

中的案例switch被视为“跳跃”。

只需在切换之前将所有对象和变量初始化,一切都会好起来的。

考虑这段代码:

switch(k)
{
    case 1:
        int t = 4;
    break;
    default:
    break;
}

这将导致“交叉初始化”错误,因为可以跳过 t 的初始化,但之后它仍然会在 scope 中,即使它一开始就没有被创建。

现在考虑一下:

switch(k)
{
    case 1:
    {
        int t = 4;
    }
    break;
    default:
    break;
}

在这里,你不会有错误,因为变量在一个块内,并且会在块的末尾(在结束时{)死掉,所以在任何情况下它都不会在范围内。

要解决第一种情况,您只需执行以下操作:

int t = 0;
switch(k)
{
    case 1:
        t = 4;
    break;
    default:
    break;
}
于 2012-07-20T12:01:47.567 回答
7

我正在将一些旧代码从 C 移植到 C++,其中包含很多 goto(到错误退出)。这个问题也出现在 switch 语句之外。

我对 gcc/g++ 的简单解决方法(使用 arm-linux-androideabi-gcc v4.6 测试):

如果你有

goto err_exit;
int a = 1;

它抱怨。

添加 -fpermissive 到您的命令行,并替换:

goto err_exit;
int a;
a = 1;

没什么好抱怨的。

于 2014-06-03T12:20:15.453 回答