2012-04-23 21 views
6

Tôi cố gắng để có một lớp cho phép ép kiểu ngầm để chắc chắn được xây dựng trong các loại, giống như unsigned int dài và kể từ khi tôi đang cố gắng để làm điều này là đúng càng tốt (đây là dự án quan trọng đầu tiên của tôi trong C++), tôi đã trúng một vấn đề kỳ lạ liên quan đến const đúng đắn:C++ quá tải chuyển đổi nhà khai thác

này hoạt động:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const 
    { 
     unsigned long int output; 
     output = (unsigned long int)data; 
     return output; 
    } 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

Nhưng điều này:

#include <iostream> 

class CustomizedInt 
{ 
private: 
    int data; 
public: 
    CustomizedInt(); 
    CustomizedInt(int input); 
    operator unsigned long int() const; 
}; 

CustomizedInt::CustomizedInt() 
{ 
    this->data = 0; 
} 

CustomizedInt::CustomizedInt(int input) 
{ 
    this->data = input; 
} 

CustomizedInt::operator unsigned long() 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 

int main() 
{ 
    CustomizedInt x; 
    unsigned long int y = x; 

    std::cout << y << std::endl; 

    return 0; 
} 

mang lại cho tôi lỗi này trong Visual Studio 2010: error C2511: 'CustomizedInt::operator unsigned long(void)' : overloaded member function not found in 'CustomizedInt'

Bây giờ, nếu tôi loại bỏ các const từ khóa từ định nghĩa điều hành, mọi thứ đều OK. Đây có phải là một lỗi? Tôi đọc rằng tôi phải sử dụng từ khóa const sau mỗi phương thức/toán tử (public) để nói rõ rằng nó không thay đổi đối tượng hiện tại theo bất kỳ cách nào.

Ngoài ra, tôi biết rằng việc xác định một nhà điều hành như vậy có thể thực hành kém, nhưng tôi không chắc chắn tôi hoàn toàn hiểu những hãy cẩn thận đi kèm. Ai đó có thể phác thảo chúng? Nó sẽ được thực hành tốt hơn để chỉ xác định một phương pháp công cộng được gọi là ToUnsignedLongInt?

Trả lời

8

Chức năng chữ ký không phù hợp với định nghĩa hàm.

operator unsigned long int() const; 

CustomizedInt::operator unsigned long() { ... } 
             ^^^ 
            const missing 

Trong trường hợp này, bạn nên đánh dấu các nhà điều hành chuyển đổi như const vì nó không ảnh hưởng đến tình trạng nội bộ của đối tượng.

Ngoài ra, hãy sử dụng danh sách khởi tạo hàm tạo để khởi tạo biến thành viên của bạn.

CustomizedInt::CustomizedInt() 
: data() 
{ 
} 

CustomizedInt::CustomizedInt(int input) 
: data(input) 
{ 
} 
+0

Vâng, cảm ơn bạn! Vì lý do nào đó, tôi nghĩ rằng tôi không cần phải lặp lại const sau khi triển khai ...Về các nhà xây dựng, có, danh sách khởi tạo là hữu ích, nhưng, trong thực hiện thực tế của tôi, dữ liệu có kiểu phức tạp và việc triển khai hàm tạo quá phức tạp đối với các danh sách khởi tạo ... –

+0

@MihaiTodor Nếu 'dữ liệu' có loại phức tạp Tôi muốn nói rằng đó là tất cả các lý do hơn để sử dụng một danh sách khởi tạo thay vì gán. [C++ FAQ] (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.6) giải thích lý do tại sao nó là thực hành tốt và liệt kê một vài ngoại lệ cho quy tắc này. – Praetorian

+0

Vâng, tôi hoàn toàn đồng ý, nhưng bạn sẽ làm gì nếu bạn cần gọi một số chức năng nhất định để khởi tạo dữ liệu đó? Tôi đang sử dụng thư viện GMP và dữ liệu là loại mpz_t, mà cần phải được khởi tạo với mpz_init (...). Làm thế nào tôi có thể gọi hàm mpz_init trên dữ liệu trong danh sách khởi tạo? –

2

Có, nếu chức năng thành viên của bạn không ảnh hưởng đến trạng thái logic của đối tượng, thì bạn thực sự nên postfix nó với const, để trình biên dịch sẽ thực thi điều đó.

Nhưng trong trường hợp đó, bạn cũng cần phải thêm const khi bạn xác định các cơ quan chức năng!

+0

Hm ... Nó hoạt động! Vì lý do nào đó, nó không hoạt động trước đây, nhưng tôi nghĩ rằng tôi phải làm một lỗi khác ở đâu đó ... Cảm ơn rất nhiều :) –

6

Bạn thể tháo const từ việc kê khai, nhưng những gì bạn gần như chắc chắn muốn làm là thêm nó để định nghĩa:

CustomizedInt::operator unsigned long() const 
{ 
    unsigned long int output; 
    output = (unsigned long int)data; 
    return output; 
} 
+0

Vâng, nhưng nếu việc thực hiện toán tử này lớn hơn ví dụ đơn giản của tôi thì sao? Tôi không muốn thêm 10 dòng mã thực thi trong tiêu đề, vì vậy tôi muốn triển khai nó bên ngoài lớp ... –

+0

@ michael85: Để lại tiêu đề như trước. Chỉ cần thêm 'const' nơi bạn thực hiện nó. Hai chữ ký cần phải khớp. –

+0

Vâng, tôi hiểu rồi. Cảm ơn. –

1

Bạn chỉ cần sao chép cùng một nguyên mẫu chức năng vào triển khai. tức là.

CustomizedInt::operator unsigned long int() const 
+0

Yeap ... Cảm ơn :) –