0

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

例如

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

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

例如

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

while( obj1 ){
   //do something repeatedly..
}

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

4

6 回答 6

3

你必须在你的类中实现一个bool重载。像这样的东西:

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

它适用于ifwhile语句。但是,如果您的编译器不支持 C++11,则不能explicit在此重载中使用关键字。

于 2013-02-19T15:12:52.630 回答
1

有多种选择。

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

而且它通常不是最好的选择。


最佳:命名状态检查。

最好的方法是使用命名的状态检查方法。例如,iostreams 有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 ...; }
};


不好:隐式转换为“私有”指针类型。

第三,如果您使用的是不支持explicit转换的编译器,即 C++03 编译器,并且由于某些莫名其妙的原因您不希望命名检查是最佳选择,那么您可以选择一个结果类型最大程度地减少意外呼叫的机会。

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

有些人提倡使用“安全布尔惯用语”,其结果是指向客户端代码无法访问的 C++03 类型的指针。


绝对最糟糕:隐式转换为bool.

最糟糕的选择就像

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

有了这个

  • 从调用代码中看不到正在检查什么条件。

  • 运算符可能会因传递Sas 函数参数而被无意调用。

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

添加 aconst只会让它稍微不那么糟糕。

它仍然非常糟糕。:-)

于 2013-02-19T15:27:55.260 回答
1

您有几种选择。可能最好的方法是重载operator bool(). 像这样:

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

 private:
   bool flag;
};

编辑:正如评论中所指出的,如果您使用它,最好通过在前面C++11添加关键字来明确操作符。explicit否则可能最好使用operator void*()

于 2013-02-19T15:12:38.470 回答
0

operator bool()需要重载才能提供此行为。但是,请仅在转换有合理的语义含义时才这样做,这是显而易见的,并且是类所有用户所期望的!

于 2013-02-19T15:14:31.987 回答
0

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

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

这将允许将您的类强制转换为布尔类型,因此可以在ifwhile等中使用它...但是重要的是要注意,这允许从您的类型到bool的隐式转换,重要的是要确保这是有道理的。

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

while (myObj.hasMoreElements())

或者

if (someObj.isValid())

这可以立即清楚正在测试的内容。但是,如果转换为bool有意义,那就去做吧。

于 2013-02-19T15:17:38.630 回答
0

您可以重载任意数量的类型转换运算符;传统的方法是operator void*()() const,为假返回一个空指针,为真返回一个非空指针(传统上this)。在 C++11 中,您也可以重载explicit operator bool() const,但如果您的编译器还不允许,则不建议这样做explicit;事实上,它bool是一个整数类型,如果没有explicit,它将转换为任何其他整数类型,这可能会导致一些令人惊讶的重载决议。

如果你这样做,你也应该重载operator!() const,所以这if ( ! myObj )也是很好的定义。

最后,您应该认真思考是否要这样做。ostream 类侥幸逃脱,因为它们是标准的一部分,每个人都可以看到、使用和了解它们,而且这种while ( someStream >> object )成语无处不在。但总的来说,对于具有两种以上可能状态的任何类,它都是误导和滥用运算符重载;一个isValidisReady任何更合适的功能。

于 2013-02-19T15:20:53.963 回答