是否可以将任何类对象作为测试表达式传递给任何测试表达式,例如if,while like ifstream对象

Can any class object be passed as test expression for any test expression such as if, while like ifstream object.

本文关键字:测试 对象 表达式 例如 任何 if while ifstream like 是否 任何类      更新时间:2023-10-16

在C++中,我可以像ifstream对象一样使用我的对象作为测试表达式吗。如果没有,为什么?

例如

ifstream ifs ("myfile.txt");
while( ifs ){
   //read and process data..
}

我有一个类,我需要重载哪个运算符才能让编译器允许我的对象作为测试表达式传递?

例如

MyClass obj1;
if( obj1 ){
   //do something..
}
while( obj1 ){
   //do something repeatedly..
}

两者都应该是有效的表达式。

您必须在类中实现bool重载。类似这样的东西:

class myClass {
    public:
        explicit operator bool() const { return condition; }
};

它将在ifwhile语句中都起作用。但是,如果编译器不支持C++11,则不能在该重载中使用explicit关键字。

您有几个选项。可能最好的方法是使operator bool()过载。像这样:

class A{
 public:
   operator bool()
   {
     return flag;
   }
 private:
   bool flag;
};

EDIT:正如评论中所指出的,如果使用C++11,最好通过在前面添加explicit关键字来明确运算符。否则,最好使用operator void*()

有很多选项。

您没有;您不必在类中实现operator bool重载。

而且;It’一般来说不是最好的选择。


最佳:命名状态检查

最好使用名为的状态检查方法。例如,iostream具有fail成员,因此您可以编写

while( !cin.fail() ) { ... }

对于你自己的班级,它可以看起来像这样:

struct S
{
    bool is_good() const { return ...; }  // Whatever name.
};


所以:explicit转换为bool

其次是explicit转换运算符。将其设为explicit可以防止if由于将某个对象作为函数参数传递而被无意调用。explicit转换运算符仍用于条件,因此您可以编写例如

while( cin ) { ... }

它在C++11中调用

explicit operator bool () const { return !fail(); }

对于你自己的班级来说,它可能看起来像

struct S
{
    explicit operator bool () const { return ...; }
};


Ungood:隐式转换为"私有"指针类型

第三,如果您使用的编译器不支持explicit转换,即C++03编译器,并且由于某种莫名其妙的原因,您不希望使用命名检查,这是最佳选择,那么您可以选择一种将意外调用的可能性降至最低的结果类型。

在C++03中,iostreams使用了到void*(而不是到bool)的隐式转换。

有些人主张使用"安全布尔习惯用法",其中结果是指向C++03中客户端代码无法访问的类型的指针。


绝对最差:隐式转换为bool

最糟糕的选择是像

struct S
{
    operator bool () { return ... }
};

有了这个

  • 从调用代码中看不出要检查的条件是什么。

  • 在传递S作为函数参数时,可能会无意中调用运算符。

  • 不能对const对象调用转换。

添加一个const只会使它稍微不那么糟糕。

它;It’还是很糟糕

您需要过载operator bool()才能提供这种行为。但是,只有当转换有合理的语义时,请这样做,这是显而易见的,也是该类所有用户所期望的!

您的编译器将尝试将表达式隐式转换为bool,因此您需要在类中添加一个类型转换运算符,如下所示:

class SomeClass {
    operator bool() {
        return true; // a boolean expression should go here.
    }
}

这将允许您的类被强制转换为布尔类型,因此允许它在ifwhile等中使用。。。然而,需要注意的是,这允许从您的类型隐式转换为bool,确保这一点很重要。

通常更明智的做法是为行为提供一种方法,例如:

while (myObj.hasMoreElements())

if (someObj.isValid())

这使得测试内容一目了然。但是,如果转换为bool是有意义的,请选择它。

您可以重载任意数量的类型转换运算符;这个传统的是operator void*()() const,返回null假指针和非空指针(传统this)真的。在C++11中,您也可以重载explicit operator bool() const,但如果您的编译器还不允许CCD_ 28;CCD_ 29是整型,如果没有explicit,它将转换对于任何其他积分类型,都可能导致一些令人惊讶的过载决议。

如果这样做,还应该重载operator!() const,因此CCD_ 32也得到了很好的定义。

最后,你应该真正反思一下你是否想这样做。ostream类可以逃脱惩罚,因为它们标准的一部分,每个看到、使用和了解它们,而且CCD_ 33习语无处不在。但总的来说,这是对运营商的误导和滥用具有两个以上可能的类的重载各州;CCD_ 34或CCD_适当的