Ý nghĩa của “operator bool () const” là gì


Câu trả lời:


141

Các hàm thành viên của biểu mẫu

operator TypeName()

là các toán tử chuyển đổi. Chúng cho phép các đối tượng của kiểu lớp được sử dụng như thể chúng thuộc kiểu TypeNamevà khi có, chúng được chuyển đổi sang TypeNamesử dụng hàm chuyển đổi.

Trong trường hợp cụ thể này, operator bool()cho phép một đối tượng của loại lớp được sử dụng như thể nó là một bool. Ví dụ: nếu bạn có một đối tượng thuộc loại lớp được đặt tên obj, bạn có thể sử dụng nó làm

if (obj)

Điều này sẽ gọi operator bool(), trả về kết quả và sử dụng kết quả làm điều kiện của if.

Cần lưu ý rằng đó operator bool()là một Ý tưởng Rất Xấu và bạn thực sự không nên sử dụng nó. Để được giải thích chi tiết về lý do tại sao nó có hại và giải pháp cho vấn đề, hãy xem "The Safe Bool Idiom."

(C ++ 0x, bản sửa đổi sắp tới của Tiêu chuẩn C ++, bổ sung hỗ trợ cho các toán tử chuyển đổi rõ ràng. Các toán tử này sẽ cho phép bạn viết một két explicit operator bool()hoạt động chính xác mà không phải thực hiện các bước triển khai Safe Bool Idiom.)


1
"used as if it was a bool" ngụ ý sai rằng bạn có thể gán giá trị boolean cho nó. Thay vào đó, trong mã của người đăng, nó tạo ra một biến tạm thời của kiểu bool liên quan đến giá trị tạm thời của col nhưng sau đó độc lập với đối tượng đã tạo ra nó. Hơn nữa, đề cập đến Thành ngữ Bool An toàn là rất tốt, nhưng chỉ để ghi nhận rằng các quan điểm trái ngược tồn tại: IMHO lời khuyên "không bao giờ thực sự sử dụng nó" là ưu tiên hàng đầu - nó cung cấp cho trình biên dịch kiểm tra chặt chẽ hơn chống lại việc lạm dụng ngớ ngẩn với cái giá là một API khó hiểu hơn điều đó có thể dẫn đến việc vô tình sử dụng sai.
Tony Delroy

1
@Tony: Chà, nó có thể được sử dụng như thể nó là một bool; vì kết quả của chuyển đổi là một rvalue ( bool), không, bạn không thể gán cho nó. Nếu đó là giá trị có thể sửa đổi (ví dụ bool&) thì bạn có thể gán cho nó. Đối với tính đúng đắn, tôi cho rằng an operator bool()luôn không chính xác vì nó cho phép sử dụng một đối tượng kiểu lớp trong một số lượng lớn các tình huống mà bạn không bao giờ muốn nó được sử dụng. Safe Bool là một giải pháp thay thế vượt trội hơn nhiều.
James McNellis

1
Vì vậy, theo đoạn cuối ngày hôm nay là hoàn toàn OK để sử dụng explicit operator bool(). Tôi có hiểu đúng?
Zingam

1
Ủy ban C ++ dường như không đồng ý với bạn về toán tử bool (). Ít nhất là cho phiên bản mới nhất của tiêu chuẩn (ví dụ: en.cppreference.com/w/cpp/utility/optional ). Hoặc có lẽ ý bạn là chỉ mã STL mới được phép sử dụng?
Joe Steele

1
@JoeSteele - Xem stackoverflow.com/a/16615725/2492801 . Các toán tử chuyển đổi rõ ràng là an toàn!
Benjamin Bihler 19/07/19

9
operator bool() const 
{
    return col != 0;
}

Xác định cách lớp có thể chuyển đổi thành giá trị boolean, constsau giá trị ()được sử dụng để chỉ ra phương thức này không thay đổi (thay đổi các thành viên của lớp này).

Bạn thường sử dụng các toán tử như sau:

airplaysdk sdkInstance;
if (sdkInstance) {
    std::cout << "Instance is active" << std::endl;
} else {
    std::cout << "Instance is in-active error!" << std::endl;
}

7

Tôi muốn cung cấp thêm mã để làm rõ ràng hơn.

struct A
{
    operator bool() const { return true; }
};

struct B
{
    explicit operator bool() const { return true; }
};

int main()
{
    A a1;
    if (a1) cout << "true" << endl; // OK: A::operator bool()
    bool na1 = a1; // OK: copy-initialization selects A::operator bool()
    bool na2 = static_cast<bool>(a1); // OK: static_cast performs direct-initialization

    B b1;     
    if (b1) cout << "true" << endl; // OK: B::operator bool()
    // bool nb1 = b1; // error: copy-initialization does not consider B::operator bool()
    bool nb2 = static_cast<bool>(b1); // OK: static_cast performs direct-initialization
}

3

Đó là implicitchức năng chuyển đổi do người dùng xác định để chuyển đổi lớp của bạn thành truehoặc false.

//usage
bool value = yourclassinstance; //yourclassinstance is converted into bool!

1

Đó là một chuyển đổi ngầm thành bool. Tức là bất cứ nơi nào cho phép chuyển đổi ngầm định, lớp của bạn có thể được chuyển đổi thành boolbằng cách gọi phương thức đó.


1

Như những người khác đã nói, đó là chuyển đổi kiểu, trong trường hợp này là a bool. Ví dụ:

class A {
    bool isItSafe;

public:
    operator bool() const
    {
        return isItSafe;
    }

    ...
};

Bây giờ tôi có thể sử dụng một đối tượng của lớp này như thể nó là một boolean:

A a;
...
if (a) {
    ....
}

1

Khi viết unique_ptr của riêng tôi, tôi đã tìm thấy trường hợp này. Do std::unique_ptroperator== :

template<class T1, class D1, class T2, class D2>
bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);

template <class T, class D>
bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;

template <class T, class D>
bool operator==(nullptr_t, const unique_ptr<T, D>& x) noexcept;

Và trường hợp thử nghiệm này từ libstdcxx :

  std::unique_ptr<int> ptr;
  if (ptr == 0)
    { }
  if (0 == ptr)
    { }
  if (ptr != 0)
    { }
  if (0 != ptr)
    { }

Lưu ý vì điều đó ptrcó một explicit operator bool() const noexcept;, vì vậy operator overload resolutionhoạt động tốt ở đây, ví dụ: các ptr == 0lựa chọn

 template <class T, class D>
 bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;`.

Nếu nó không có explicittừ khóa ở đây, ptrin ptr == 0sẽ được chuyển thành bool, sau đó boolsẽ được chuyển thành int, bởi vì bool operator==(int, int)được tích hợp sẵn và 0int. Những gì đang chờ đợi chúng tôi là lỗi giải quyết quá tải không rõ ràng.

Dưới đây là một ví dụ Tối thiểu, Hoàn chỉnh và Có thể xác minh :

#include <cstddef>
struct A
{
    constexpr A(std::nullptr_t) {}
    operator bool() 
    {
        return true;
    }
};

constexpr bool operator ==(A, A) noexcept
{
    return true;
}

constexpr bool operator ==(A, std::nullptr_t) noexcept
{
    return true;
}

constexpr bool operator ==(std::nullptr_t, A) noexcept
{
    return true;
}

int main()
{
    A a1(nullptr);
    A a2(0);
    a1 == 0;
}

gcc :

prog.cc: In function 'int main()':
prog.cc:30:8: error: ambiguous overload for 'operator==' (operand types are 'A' and 'int')
   30 |     a1 == 0;
      |     ~~ ^~ ~
      |     |     |
      |     A     int
prog.cc:30:8: note: candidate: 'operator==(int, int)' <built-in>
   30 |     a1 == 0;
      |     ~~~^~~~
prog.cc:11:16: note: candidate: 'constexpr bool operator==(A, A)'
   11 | constexpr bool operator ==(A, A) noexcept
      |                ^~~~~~~~
prog.cc:16:16: note: candidate: 'constexpr bool operator==(A, std::nullptr_t)'
   16 | constexpr bool operator ==(A, std::nullptr_t) noexcept
      |                ^~~~~~~~

leng keng :

prog.cc:30:8: error: use of overloaded operator '==' is ambiguous (with operand types 'A' and 'int')
    a1 == 0;
    ~~ ^  ~
prog.cc:16:16: note: candidate function
constexpr bool operator ==(A, std::nullptr_t) noexcept
               ^
prog.cc:11:16: note: candidate function
constexpr bool operator ==(A, A) noexcept
               ^
prog.cc:30:8: note: built-in candidate operator==(int, int)
    a1 == 0;
       ^
prog.cc:30:8: note: built-in candidate operator==(float, int)
prog.cc:30:8: note: built-in candidate operator==(double, int)
prog.cc:30:8: note: built-in candidate operator==(long double, int)
prog.cc:30:8: note: built-in candidate operator==(__float128, int)
prog.cc:30:8: note: built-in candidate operator==(int, float)
prog.cc:30:8: note: built-in candidate operator==(int, double)
prog.cc:30:8: note: built-in candidate operator==(int, long double)
prog.cc:30:8: note: built-in candidate operator==(int, __float128)
prog.cc:30:8: note: built-in candidate operator==(int, long)
prog.cc:30:8: note: built-in candidate operator==(int, long long)
prog.cc:30:8: note: built-in candidate operator==(int, __int128)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, int)
prog.cc:30:8: note: built-in candidate operator==(long long, int)
prog.cc:30:8: note: built-in candidate operator==(__int128, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, int)
prog.cc:30:8: note: built-in candidate operator==(float, float)
prog.cc:30:8: note: built-in candidate operator==(float, double)
prog.cc:30:8: note: built-in candidate operator==(float, long double)
prog.cc:30:8: note: built-in candidate operator==(float, __float128)
prog.cc:30:8: note: built-in candidate operator==(float, long)
prog.cc:30:8: note: built-in candidate operator==(float, long long)
prog.cc:30:8: note: built-in candidate operator==(float, __int128)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(float, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(double, float)
prog.cc:30:8: note: built-in candidate operator==(double, double)
prog.cc:30:8: note: built-in candidate operator==(double, long double)
prog.cc:30:8: note: built-in candidate operator==(double, __float128)
prog.cc:30:8: note: built-in candidate operator==(double, long)
prog.cc:30:8: note: built-in candidate operator==(double, long long)
prog.cc:30:8: note: built-in candidate operator==(double, __int128)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, float)
prog.cc:30:8: note: built-in candidate operator==(long double, double)
prog.cc:30:8: note: built-in candidate operator==(long double, long double)
prog.cc:30:8: note: built-in candidate operator==(long double, __float128)
prog.cc:30:8: note: built-in candidate operator==(long double, long)
prog.cc:30:8: note: built-in candidate operator==(long double, long long)
prog.cc:30:8: note: built-in candidate operator==(long double, __int128)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long double, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, float)
prog.cc:30:8: note: built-in candidate operator==(__float128, double)
prog.cc:30:8: note: built-in candidate operator==(__float128, long double)
prog.cc:30:8: note: built-in candidate operator==(__float128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__float128, long)
prog.cc:30:8: note: built-in candidate operator==(__float128, long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__float128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long, float)
prog.cc:30:8: note: built-in candidate operator==(long, double)
prog.cc:30:8: note: built-in candidate operator==(long, long double)
prog.cc:30:8: note: built-in candidate operator==(long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long, long)
prog.cc:30:8: note: built-in candidate operator==(long, long long)
prog.cc:30:8: note: built-in candidate operator==(long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, float)
prog.cc:30:8: note: built-in candidate operator==(long long, double)
prog.cc:30:8: note: built-in candidate operator==(long long, long double)
prog.cc:30:8: note: built-in candidate operator==(long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(long long, long)
prog.cc:30:8: note: built-in candidate operator==(long long, long long)
prog.cc:30:8: note: built-in candidate operator==(long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, float)
prog.cc:30:8: note: built-in candidate operator==(__int128, double)
prog.cc:30:8: note: built-in candidate operator==(__int128, long double)
prog.cc:30:8: note: built-in candidate operator==(__int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(__int128, long)
prog.cc:30:8: note: built-in candidate operator==(__int128, long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(__int128, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned int, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned long long, unsigned __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, float)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long double)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __float128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, __int128)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned int)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned long long)
prog.cc:30:8: note: built-in candidate operator==(unsigned __int128, unsigned __int128)
1 error generated.

-4

Một cách sử dụng phổ biến khác là cho các vùng chứa std để thực hiện so sánh bình đẳng trên các giá trị chính bên trong các đối tượng tùy chỉnh

class Foo
{
    public: int val;
};

class Comparer { public:
bool operator () (Foo& a, Foo&b) const {
return a.val == b.val; 
};

class Blah
{
std::set< Foo, Comparer > _mySet;
};

2
Đây là ví dụ sử dụng operator ()không operator bool. Chúng hoàn toàn khác nhau. operator ()là toán tử cuộc gọi, để a Comparercó thể được gọi dưới dạng một hàm. Điều đó operator ()chỉ xảy ra để trả về bool, nhưng điều đó không làm cho nó giống như operator bool, mà chỉ đơn giản là cho phép một diễn viên ngầm bool.
Michael Dorst
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.