假设我有一个班级:
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
答案 0 :(得分:4)
您不能重载类,但可以使用转换运算符,以便根据该上下文中的预期参数自动转换为不同的类型。在您的情况下,由于val
是int
,您可以将转化重载为int
,如下所示:
operator int() const { return val; }
现在,只要需要int
,并且您提供foo
,就会应用此转化。
有一些限制。例如,如果将foo
传递给函数模板,其中相应参数的类型是通用的,则该位置将不会进行转换。转换也不会影响其他不强制执行类型的表达式。例如,如果f
的类型为foo
,则&f
将始终为foo*
类型,而不是int*
。对于大多数实际应用,所有这些正是您所需要的。但我相信C风格的变量printf
就是这种情况,没有明确定义的期望类型。更好地使用C ++风格的调用或显式的强制转换static_cast<int>(f)
。
如果你不能接受,那么你就麻烦了:C ++逻辑无法在这里推断出你需要int
的事实,因为你在%d
中包含了int val
一些字符串常量。类型转换是编译时的事情,而格式字符串的解释是在运行时完成的(除非以gcc的方式生成警告)。编译器不知道该参数需要什么类型,因此它不知道要执行什么转换,因此你必须以某种方式帮助他。
只要这个foo
是foo
的唯一成员,并且在这个类中没有虚函数,并且neithe ris有一个带有任何数据成员或virtula函数的基类,类printf
的对象的内存布局通常与普通整数的内存布局相同。这意味着即使没有任何转换,无类型的C风格{{1}}也无法区分。但依靠这种风格真的很糟糕,所以我建议不要使用它。
答案 1 :(得分: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
最令人困惑的。
答案 2 :(得分:2)
不,这是不可能的。
首先,逗号运算符不适用于此处,因为逗号用于分隔printf参数,该参数优先于用作运算符的逗号。
添加转换运算符没有帮助,因为printf的声明是
printf(const char *,...);
这意味着编译器不知道参数应该是什么类型(除了第一个),因此它不会进行任何转换。