Làm cách nào để nạp chồng toán tử ++ theo hai cách khác nhau cho hậu tố a ++ và tiền tố ++ a?


Câu trả lời:


165

Sẽ như thế này:

class Number 
{
    public:
        Number& operator++ ()     // prefix ++
        {
           // Do work on this.   (increment your object here)
           return *this;
        }

        // You want to make the ++ operator work like the standard operators
        // The simple way to do this is to implement postfix in terms of prefix.
        //
        Number  operator++ (int)  // postfix ++
        {
           Number result(*this);   // make a copy for result
           ++(*this);              // Now use the prefix version to do the work
           return result;          // return the copy (the old) value.
        }
}; 

15
Mã này cũng cho thấy sự khác biệt về hiệu suất tiền tố so với hậu tố. Nếu đối tượng bạn đang trả về không vừa với thanh ghi CPU, thì bạn đang thực hiện một thao tác sao chép tốn kém. Điều này là tốt nếu bạn cần sử dụng giá trị tăng trước, nhưng nếu bạn không sử dụng, hậu tố sẽ tốt hơn nhiều. Một ví dụ sẽ là một iterator nơi bạn thường sử dụng: for (pos = c.begin (); ...; ++ pos) {} thay vì pos ++
Eric

22
@Eric: Bạn đã sửa nó toàn bộ ngoại trừ một câu ở giữa nơi bạn trộn. Tiền tố của nó tốt hơn.
Martin York

6
Tại sao lại Number operator++ (int)lấy intmột tham số mặc dù bạn không sử dụng nó?
Sean Letendre

10
@SeanLetendre: Nó không thực sự nhận tham số int. Đó là một thông số giả. Nhưng các nhà thiết kế ngôn ngữ C ++ đã phải xác định một cách để phân biệt giữa các định nghĩa chức năng tiền tố và hậu tố. Đây là quyết định thiết kế mà họ đã thực hiện.
Martin York

2
@EnricoMariaDeAngelis: Cú pháp phân biệt cả hai. ++xlà tiền tố và do đó gọi operator++() trong khi x++là postfix và do đó gọioperator++(int)
Martin York

34

Sự khác biệt nằm ở việc bạn chọn chữ ký nào cho (các) quá tải của mình operator ++.

Được trích dẫn từ bài viết liên quan về chủ đề này trong Câu hỏi thường gặp về C ++ (vào đó để biết thêm chi tiết):

class Number {
  public:
    Number& operator++ ();     // prefix ++: no parameter, returns a reference
    Number  operator++ (int);  // postfix ++: dummy parameter, returns a value
};

Tái bút: Khi tôi phát hiện ra điều này, tất cả những gì tôi thấy ban đầu là tham số giả, nhưng các kiểu trả về khác nhau thực sự thú vị hơn; họ có thể giải thích lý do tại sao ++xđược coi là hiệu quả hơn x++ nói chung .


17

Bạn có hai cách để nạp chồng hai toán tử (tiền tố / hậu tố) ++ cho kiểu T:

Phương pháp đối tượng:

Đây là cách dễ nhất, sử dụng thành ngữ OOP "phổ biến".

class T
{
    public :
        T & operator++() // ++A
        {
            // Do increment of "this" value
            return *this ;
        }

        T operator++(int) // A++
        {
           T temp = *this ;
           // Do increment of "this" value
           return temp ;
        }
} ;

Đối tượng không phải hàm thành viên:

Đây là một cách khác để thực hiện việc này: Miễn là các hàm nằm trong cùng không gian tên với đối tượng mà chúng cũng đang tham chiếu, chúng sẽ được xem xét khi trình biên dịch sẽ tìm kiếm một fonction để xử lý ++t ;hoặc t++ ;mã:

class T
{
    // etc.
} ;


T & operator++(T & p_oRight) // ++A
{
   // Do increment of p_oRight value
   return p_oRight ;
}

T operator++(T & p_oRight, int) // A++
{
   T oCopy ;
   // Copy p_oRight into oCopy
   // Do increment of p_oRight value
   return oCopy ;
}

Điều quan trọng cần nhớ là, theo quan điểm C ++ (bao gồm cả quan điểm trình biên dịch C ++), các hàm không phải thành viên đó vẫn là một phần của giao diện T (miễn là chúng nằm trong cùng một không gian tên).

Có hai lợi thế tiềm năng của ký hiệu hàm không phải thành viên:

  • Nếu bạn quản lý để mã hóa chúng mà không làm cho chúng trở thành bạn của T, thì bạn đã tăng tính đóng gói của T
  • bạn có thể áp dụng điều này ngay cả cho các lớp hoặc cấu trúc có mã mà bạn không sở hữu. Đây là một cách không xâm nhập để nâng cao giao diện của một đối tượng mà không cần sửa đổi khai báo của nó.

1

Khai báo như vậy:

class A
{
public:
    A& operator++();    //Prefix (++a)
    A operator++(int); //Postfix (a++)

};

Thực hiện đúng cách - không gây rối với những gì mọi người biết họ làm (tăng rồi sử dụng, sử dụng rồi tăng dần).


-2

Tôi biết là đã muộn, nhưng tôi đã gặp vấn đề tương tự và đã tìm ra một giải pháp đơn giản hơn. Đừng hiểu sai ý tôi, đây là giải pháp tương tự như giải pháp hàng đầu (được đăng bởi Martin York). Nó chỉ đơn giản hơn một chút . Chỉ một chút. Nó đây:

class Number
{
        public:

              /*prefix*/  
        Number& operator++ ()
        {
            /*Do stuff */
            return *this;
        }

            /*postfix*/
        Number& operator++ (int) 
        {
            ++(*this); //using the prefix operator from before
            return *this;
        }
};

Giải pháp trên đơn giản hơn một chút vì nó không sử dụng đối tượng tạm thời trong phương thức postfix.


6
Đây không phải là tiêu chuẩn. Toán tử postfix ++ phải trả về giá trị trước khi tăng dần, không phải sau.
Kuilin Li

Câu trả lời này không chính xác. Tạm thời là bắt buộc.
Rian Quinn
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.