【问题标题】:C++ use struct as some typeC++ 使用 struct 作为某种类型
【发布时间】:2018-05-21 23:15:35
【问题描述】:

假设我有这个结构:

struct shape{
    int type;
    shape(){}
    shape(int _type){type = _type;}
};

是否可以直接将形状用作int?在这种情况下,shape 将采用其类型的值。例如:

shape s(2);
if     (s == 1) cout<<"this shape is a circle"<<endl;
else if(s == 2) cout<<"this shape is a triangle"<<endl;
else if(s == 3) cout<<"this shape is a rectangle"<<endl;
//...

一般来说,是否可以使用一个结构,以便它假定其属性之一的选定值?在 shape 的情况下,它是一个 int,但它可以是一个字符串或任何其他类型。


编辑:我尝试了@Jarod42 建议的代码,使用字符串作为类型:

struct shape{
    string type;
    shape(){}
    shape(string _type){type = _type;}
    operator string() const {return type;}
}; 

当我写作时

shape s1("circle");
string s2 = "circle";
if(s1 == s2){ ...

它说 error: no match for 'operator=='(操作数类型是 'shape' 和 'std::string),尽管使用 int 作为类型,它工作正常。

【问题讨论】:

  • 仅供参考,如果相当危险且通常不明智,则沿着这条路走下去。你经常隐含地购买你的类不是为这些 API 设计的。这只有在你有明确的 is-a 关系时才有意义(你的 shape 类绝对没有 ints+3 是什么意思?这很重要,因为它不再导致编译错误。)跨度>
  • cout &lt;&lt; "this shape is a " &lt;&lt; (s == 1 ? "circle" : s == 2 ? "triangle" : s == 3 ? "rectangle" : "(unknown shape)") &lt;&lt; "\n"; 或者只使用switch 语句。 ;)
  • @Frank 这就是为什么您可以进行转换explicit,但当然,对于更高度开发的shape API 来说,拥有流运算符、比较运算符等也可能更有意义让类的最终用户以相关方式访问形状,而不会暴露实现细节。当然你已经知道了。
  • int 是原始数据类型,但字符串不是。您需要重载 == 运算符才能在 if 条件下进行比较。

标签: c++ struct


【解决方案1】:

你可以加operator int:

struct shape{
    int type;
    shape(){}
    shape(int _type) : type(_type) {}

    operator int() const { return type; }
};

【讨论】:

  • 这适用于任何类型吗?例如,operator string() const ... 或者即使我有自己的结构,operator s() const ... 是否正确?
  • 是的,您可以在shape 中定义一个转换运算符,将其实例“转换”为您想要的任何其他类型。
  • 是的,您甚至可以返回参考。
  • 我尝试使用字符串作为类型,它给了我no match for operator== between shape and string
  • 因为std::stringoperator ==的模板,所以没有operator ==匹配参数。在这种情况下,您可能会显式转换为字符串:std::string(s) == "circle"
【解决方案2】:

通常您可以使用operator T,其中T 是您要转换为的类型。如果要强制使用static_cast&lt;T&gt;(my_shape),那么可以在前面加上关键字explicit

struct shape
{
    int type;

    shape() = default;
    shape(int _type) : type{ _type } {}

    operator int() const { return type; }
    explicit operator float() const { return type; }

    operator std::string() const
    {
        switch (type)
        {
            case 1:
                return "circle";
            case 2:
                return "triangle";
            case 3:
                return "rectangle";
            default:
                break;
        }
        return "(unknown shape)";
    }
};

这将适用于内置类型(intfloatdouble)、标准类型(std::stringstd::complex)、自定义结构/类类型,甚至是指针或引用(例如,如果您有一个静态值数组)。您可能需要考虑是否需要这些转换运算符(封装是另一回事),但从概念上讲,这是您将如何做到的。

在这个例子中,你可能还想引入一个enum 来存储你的类型值:

struct shape
{
    enum type_t
    {
        circle = 1,
        triangle,
        rectangle
    };

    type_t type;

    operator std::string() const
    {
        switch (type)
        {
            case circle:
                return "circle";
            case triangle:
                return "triangle";
            case rectangle:
                return "rectangle";
            default:
                break;
        }
        return "(unknown shape)";
    }

    shape(type_t _type) : type{ _type } {}

    // rest of class as before
};

【讨论】:

  • 如何比较形状 s 和字符串?当我尝试s == "circle" 时,它说形状和字符串之间没有运算符 ==。
  • 您可以将其实现为成员函数bool operator==(std::string s) const 作为结构定义的一部分。在该函数中,您可以使用 switchtype(如上),然后针对每种情况测试字符串的值:case circle: return s == "circle";
【解决方案3】:

虽然使用强制转换运算符是一种方法,如 @Jarod42 所示,但我建议让操作更加明确。

  1. 添加一个函数来获取类型。
  2. if-else 语句中使用函数调用和返回值。

struct shape{
    int type;
    shape(){}
    shape(int _type){type = _type;}
    int getType() const { return type;}
};

然后

shape s(2);
int type = s.getType();
if     (type == 1) cout<<"this shape is a circle"<<endl;
else if(type == 2) cout<<"this shape is a triangle"<<endl;
else if(type == 3) cout<<"this shape is a rectangle"<<endl;

【讨论】:

  • 恐怕这不是我要找的,我想明确地使用结构作为其属性之一的类型(无论是 int、string 还是其他)
  • @Daniel,当然,这是您的选择。根据我的经验,我发现这种隐式转换会导致代码错误且难以理解。
  • 我问只是因为它让我好奇,我不会在认真的代码中添加这种做法
  • @RSahu 转换运算符不必是隐式的。您可以在运算符前添加explicit 说明符,然后它只能通过static_cast 使用。
  • @RSahu 它也被认为是 bad practice in programming to repeat yourself,所以 OP 的 cout 调用“应该”被简化。
【解决方案4】:

如果你最终只想通过字符串比较形状,那么有一个更简单且更安全的解决方案:

struct shape{
    std::string type;

    shape() {}

    bool operator==(std::string const& rhs) const {
      return type == rhs;
    }
};

// and if you want to be able to do string == shape.
bool operator==(std::string const& lhs, shape const& rhs) {
  return rhs == lhs;
}

【讨论】:

  • @Jarod42 好吧,您不必为了满足提问者的目标而这样做,但总的来说,这绝对是一个好主意,我已将其添加到答案中。
猜你喜欢
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多