【问题标题】:Pass empty string to constructor将空字符串传递给构造函数
【发布时间】:2016-10-12 14:17:59
【问题描述】:

注意:我还是 c++ 新手,虽然这可能是一个简单的问题,但我无法找到解决方案。

目的:

我想将一个空字符串(就像在 java/C# 中那样)传递给我的构造函数。我收到一个错误:

error: no matching function for call to 'ReturnObject::ReturnObject(ResultCode::ClientCode, const char [1])'
         return new ReturnObject(ResultCode::ClientCode::enum_FailedOpeningClientSocket, "");

ReturnObject 的目的是封装一个enum 和一个string

这个错误是什么意思,我该如何解决?

我尝试将我的构造函数参数从QString data 更改为char data 并使用'' 调用,但这导致了错误empty character constant

调用代码:

return new ReturnObject(ResultCode::ClientCode::enum_FailedSocketConnection, "");

标题:

class ReturnObject
{
public:
    ReturnObject(ResultCode enum_code, QString data);

    QString getData();
    ResultCode getCode();

private:
    ResultCode e_code;
    QString data_string;

};

实施

#include "returnobject.h"

ReturnObject::ReturnObject(){
    data_string="WARN";
}

ReturnObject::ReturnObject(ResultCode enum_code, QString data)
    : e_code(enum_code)
    , data_string(data)
{}

ResultCode ReturnObject::getCode()
{
    return e_code;
}

QString ReturnObject::getData()
{
    return data_string;
}

感谢 wasthishelpful 和一些 cmets,我犯了一个可悲的逻辑错误,导致我查看了错误的参数,解决方案是我应该转换我的枚举类 ResultCode 这是父级类到嵌套的classes 之一,在本例中为ClientCode,如下所示从我的枚举类标题中看到

枚举.h

#ifndef ENUMS_H
#define ENUMS_H

class ResultCode{
public:
    enum class LoginDialogCode{
        enum_LoginSuccess=0,
        enum_InternetOffline=1,
        enum_ServerOffline=2,
        enum_InvalidLoginPass=3,
        enum_EmptyLoginPass=4,
        enum_FailedRetreivingServerList=5,
        enum_TokenFailed=6
    };

    enum class ClientCode{
        enum_SentSuccess=10,
        enum_FailedOpeningClientSocket=11,
        enum_FailedClientSocketConnection=12,
        enum_FailedWritingtoClientSocket=13,
        enum_FailedReadingfromClientSocket=14
    };

    enum class ServerCode{
        enum_ReceivedSuccess=20,
        enum_FailedOpeningListenSocket=21,
        enum_FailedBindingtoListenSocket=22,
        enum_FailedAcceptingListenSocket=23,
        enum_FailedWritingtoListenSocket=24,
        enum_FailedReadingfromListenSocket=25
    };
};

#endif // ENUMS_H

【问题讨论】:

  • ResultCode::ClientCode::enum_FailedSocketConnection的类型是什么?
  • 您期望ResultCode,但您传递了ClientCode
  • 没有构造函数采用ResultCode::ClientCode 参数,但您已经确定第二个参数是您忽略第一个参数的问题。
  • @GillBates 我真是太愚蠢了,感谢您指出这一点
  • @molbdnilo 谢谢,我没看到!

标签: c++ qt c++11 char qstring


【解决方案1】:

您的错误不在第二个参数上,而是在第一个参数上。从你的问题,我猜你有这样的代码:

struct ReturnCode
{
    enum class ClientCode
    {
        enum_FailedSocketConnection,
        // other values
    };
};

所以你最终得到了两种声明的类型:ReturnCodeReturnCode::ClientCode。查看您的构造函数声明:

`ReturnObject::ReturnObject(ResultCode enum_code, QString data)`

它需要ReturnCode 类型的对象作为第一个参数,同时查看您的调用:

ReturnObject(ResultCode::ClientCode::enum_FailedSocketConnection, "")

您将ReturnCode::ClientCode 类型的对象作为第一个参数传递。

您可以像这样更改您的代码:

class ReturnObject
{
public:
    ReturnObject(ResultCode::ClientCode enum_code, QString data);

    QString getData();
    ResultCode::ClientCode getCode();

private:
    ResultCode::ClientCode e_code;
    QString data_string;

};

一旦你来到这里。您可以考虑将枚举从ResultCode中取出:

enum class ClientCode
{
    enum_FailedSocketConnection,
    // other values
};

class ReturnObject
{
public:
    ReturnObject(ClientCode enum_code, QString data);

    QString getData();
    ClientCode getCode();

private:
    ClientCode e_code;
    QString data_string;

};

这遵循Zen of Python:“平面优于嵌套”。恕我直言,这在 C++ 中也是如此。

编辑:

来自您的 cmets,我们在 XY problem 上,您的代码需要重新设计。这是第一个命题:

#include <type_traits>

enum class ClientCode{
    // ...
    enum_FailedClientSocketConnection=12,
    // ...
};

template<typename T>
struct ReturnObject
{
    static_assert(std::is_enum<T>::value, "T should be an enum");

    const T e_code;
    const QString data_string;
};

template<typename T>
ReturnObject<T> make_return_object(T e_code, std::string data_string)
{
    return ReturnObject<T>{e_code, data_string};
}

// usage

return make_return_object(
    ClientCode::enum_FailedClientSocketConnection, ""
);

我删除了公共 const 成员的访问器 getDatagetCode:它们只是被读取,不应该针对给定的返回对象更改,所以让它们成为公共的,并使用 const 限定符来防止修改。

我用模板来表示代码,用static_assert检查给定的类型是一个枚举。

缺点是:

  • 您可以传递任何枚举,而不仅仅是您的结果代码。
  • make_return_object 将为每个不同的枚举返回不同的类型。

【讨论】:

  • 见鬼!谢谢。但是有一个问题,您的派生代码几乎是正确的,请参阅我的更新,我有一个嵌套枚举。我需要将我的ResultCode::enum_FailedOpeningClientSocket 转换为ResultCode::ClientCode 对象。这应该怎么做,而不是我应该使用哪个,动态的还是静态的?
  • 既不是dynamic_cast 也不是static_cast:嵌套类型与其“嵌套”类型无关,并且它们之间不能被强制转换,就像你在使用继承。嵌套类型在这里就像一个带有privateprotected 选项的命名空间。为什么需要ResultCode?除非您想将嵌套在 ResultCodeas 中的任何枚举作为参数传递给您的函数,但我在这里看不到重点:如果您需要 ClientCode,则不应允许传递任何其他内容,以及执行方式也就是将参数声明为ClientCode
  • 事实上这正是我需要ResultCode的原因,因为我将在几个不同的类中使用这个ReturnObject,我需要一个可以插入来自ResultCode的任何枚举的类和一个支持字符串/ (字符数组)。我刚刚意识到我不需要ResultCode 作为enum,而是作为struct,正如你所指出的。但由于我可以从ResultCode 插入任何enum,因此我需要对它进行类型转换以执行适当的enum class。这就是我所指的,这应该是像(ResultCode::ClientCode)ResultCode::ClientCode::enum_Failed... 这样的普通演员。我现在正在测试这个......
  • 那应该 NOT 是演员表 :) 你在这里的设计是错误的。我会给你一个答案,但我今天不能
  • 谢谢你的麻烦,我暂时将所有枚举合并到一个类中。我热切地等待您提出的解决方案/新设计,我很想对此提出新的意见!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-27
  • 1970-01-01
  • 2023-03-26
  • 1970-01-01
  • 2018-08-31
  • 2023-03-16
相关资源
最近更新 更多