【问题标题】:Overload the class itself重载类本身
【发布时间】:2012-09-08 21:30:00
【问题描述】:

假设我有一个班级:

class foo
{
    ....
    //some constructors here set val=34
    ....
    private:
    int val;
    int & foo::operator,()
    {
      return val;
    }
};

我希望能够将其用作:

foo bar;
printf("  %d ", bar);   //i need to get value of bar.val
                        //with just using bar itself with
                        //using an overloading
                        //but , overloading does not work
                        //i need to get 34 without using bar.val
                        //i need this without any getter 
                        //i need val to be private

问题:这种重载可能吗?如果是,怎么做?

我试过了:

int foo::operator int()
{
    return val;
}

但它说“可能未在转换函数上指定返回类型”:(

我试过了:

operator int() const { return val; } 

转换只能在 printf 和 cout 之外进行。

 int e=foo;
 printf(" %d ",e); //works 

【问题讨论】:

  • operator int() 应该可以工作。转换运算符(如果您需要术语)。
  • 我收到一个错误:可能未在转换函数上指定返回类型
  • printf 不是类型安全的。更喜欢 cout。
  • @tuğrulbüyükışık,转换运算符没有返回类型。它们通常也应标记为 explicit(至少在 C++11 中)并且是逻辑转换。
  • 难道没有空运算符或仅使用类对象名称的东西就足以使用该重载吗?

标签: c++ class operator-overloading


【解决方案1】:

你不能重载一个类,但是你可以使用一个转换操作符,它会根据上下文中的预期参数自动转换为不同的类型。在您的情况下,由于valint,您可以像这样重载转换为int

operator int() const { return val; }

现在只要需要int,并且您提供foo,就会应用此转换。

有一些限制。例如,如果您将foo 传递给相应参数的类型为泛型的函数模板,则该位置将不会进行转换。转换也不会影响不强制类型的其他表达式。例如,如果ffoo 类型,那么&f 将始终是foo* 类型,而不是int*。对于大多数实际应用,这一切正是您所需要的。但我相信 C 风格的可变参数 printf 正是没有明确定义的预期类型的​​这种情况。最好使用 C++ 风格的调用,或显式转换 static_cast<int>(f)

如果两者都不适合您,那么您就有麻烦了:C++ 逻辑无法推断出您在此处需要int,仅仅因为您在某些字符串常量中包含了%d。类型转换是编译时的事情,而格式字符串的解释是在运行时完成的(除了像 gcc 那样生成警告时)。编译器不知道该参数需要是什么类型,因此它不知道要执行什么转换,因此您必须以某种方式帮助他。

只要这个int valfoo的唯一成员,并且这个类中也没有虚函数,并且没有任何数据成员的基类或虚拟函数,那么内存布局foo 类的对象通常与普通整数的对象相同。这意味着无类型的 C 风格 printf 将无法区分,即使根本没有任何转换。但是依赖这个真的很糟糕,所以我建议不要使用它。

【讨论】:

  • 对 printf 没有帮助,它接受一个变量参数列表,所以编译器不知道它需要转换。
  • 给出错误 atom2.cpp(61):错误 C4430:缺少类型说明符 - 假定为 int。注意:C++ 不支持默认整数 atom2.cpp(63):警告 C4183:'$S1':缺少返回类型;假定是返回“int”的成员函数
  • 运算符 int() const { return val; } 当我使用 int m=foo;printf(" %d ",m);至少有 m=foo 工作。谢谢
【解决方案2】:

不要过度使用逗号或其他可怕的东西。 printf 具有省略号参数,因此它接受您提供给它的任何内容,您必须确保您提供的内容是正确的。保持简单:

class foo
{
    ....
    //some constructors here set val=34
    ....
private:
    int val;
public:
    int value()
    {
      return val;
    }
};

int main()
{
    foo bar;
    printf("  %d ", bar.value());   //you get value of bar.val
}

printf 不会调用您栏上的任何运算符(包括转换运算符),因此这些对您没有帮助。即使你有operator int(),你仍然应该这样写:

    printf("  %d ", (int)bar);   //you get value of bar.val

这样看起来也好不了多少。甚至:

    printf("  %d ", +bar);   //you get value of bar.val

最令人困惑的。

【讨论】:

  • 请问我可以不使用 getter 做其他事情吗?
  • 是的,我提供了几个带有运算符 int 的示例,但这些被认为比显式 getter 更糟糕。
  • MVG 的运算符 int() const { return val; } 当我使用 int m=foo;printf(" %d ",m);至少有 m=foo 工作。谢谢
【解决方案3】:

不,这是不可能的。

首先,逗号运算符在这里不适用,因为逗号用于分隔 printf 参数,它优先于用作运算符的逗号。

添加转换运算符没有帮助,因为 printf 的声明是

printf(const char *,...);

这意味着编译器不知道参数应该是什么类型(除了第一个),所以它不会做任何转换。

【讨论】:

  • MVG 的运算符 int() const { return val; } 当我使用 int m=foo;printf(" %d ",m);至少有 m=foo 工作。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-12-14
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
相关资源
最近更新 更多