2011-12-10 32 views
8

Vì vậy, tôi đã có một kỳ thi ngày khác, và một trong những câu hỏi là cái gì đó rất tương tự như sau:Quá tải static_cast?

Chúng tôi có một lớp được gọi là Square nắm giữ một biến int side. Làm thế nào chúng ta có thể làm cho nó có thể rằng cout << static_cast<int>(aSquare) <<endl; sẽ in ra khu vực của aSquare?

Điều đó có thể thực hiện được không?

Trả lời

18

Có thể thực hiện công việc đó, nhưng không thể thực hiện quá tải static_cast<>(). Bạn làm như vậy bằng cách quá tải toán tử định kiểu:

class Square 
{ 
public: 
    Square(int side) : side(side) {} 
    operator int() const { return side * side; } // overloaded typecast operator 
private: 
    int side; 
}; 

// ... 

// Compiler calls Square::operator int() to convert aSquare into an int 
cout << static_cast<int>(aSquare) <<endl; 

Hãy coi chừng toán tử quá tải thường không gây hại nhiều hơn lợi. Họ thực hiện rất nhiều hoạt động diễn viên tiềm ẩn vô nghĩa có thể. Khi bạn đọc đoạn mã này dưới đây, bạn có nghĩ "a sẽ lấy diện tích s" không?

Square aSquare; 
int a = aSquare; // What the heck does this do? 

Tôi chắc chắn không. Điều này làm cho cảm giác cách hơn và nhiều hơn nữa có thể đọc được:

Square aSquare; 
int a = aSquare.GetArea(); 

Chưa kể rằng thường bạn muốn để có thể truy cập vào các thông tin khác về Square, như GetSide() hoặc GetApothem() hoặc GetPerimeter() hoặc bất cứ điều gì. operator int() rõ ràng chỉ có thể trả về một int và bạn không thể có nhiều operator int() s làm thành viên của một lớp học.

Đây là một tình huống mà các operator int() làm cho mã biên dịch nhưng chẳng có ý nghĩa gì:

Square s; 
if(s > 42) {} // Huh?! 

có nghĩa là gì cho một Square để được lớn hơn 42? Điều đó là vô nghĩa, nhưng với mã số operator int() ở trên sẽ biên dịch là Shape giờ đây có thể được chuyển đổi thành một số int có thể được so sánh với một số int khác với giá trị 4.

Vì vậy, đừng viết các toán tử được định kiểu như vậy. Trong thực tế, nếu bạn đang quá tải các toán tử định kiểu, bạn có thể muốn suy nghĩ hai lần về những gì bạn đang làm. Thực tế chỉ có một vài trường hợp việc quá tải toán tử định kiểu có ích trong C++ hiện đại (ví dụ: the safe bool idiom).

+0

+1: một lớp Square có thể sử dụng một số phương pháp khác, ví dụ: 'int GetSideLength() const',' int GetPerimeter() const', và nó nhằm mục đích định hướng rằng một phương thức được đặt tên nên được sử dụng cho 'GetArea()'. – rwong

+0

Cảm ơn câu trả lời phức tạp. – Radix

+2

@ Trong silico: Với C++ 11 thành ngữ bool an toàn không còn cần thiết, vì C++ 11 hỗ trợ từ khóa 'tường minh' cho các toán tử chuyển đổi. – smerlin

1

Bạn có thể cung cấp một nhà điều hành chuyển đổi cho lớp vuông:

class Square 
{ 
public: 
    operator int() 
    { 
     return side * side; 
    } 
private: 
    int side; 
}; 
+0

nó phải trả lại khu vực, không phải là bên – Dani

+2

Giữ đúng cho các trường hợp hình vuông rất nhỏ. –

+2

@Dani: Tôi nghĩ bạn đã bỏ lỡ vấn đề. Tôi chắc chắn OP biết cách tính diện tích. Câu hỏi đã được trả lời một cách chính xác làm thế nào để có được một int từ đối tượng vuông là một phần kỹ thuật của câu hỏi. –

4

Bạn có thể nạp chồng toán tử dàn diễn viên:

struct square { 
    operator int() const { 
    return (side * side); 
    } 
    int side; 
}; 

Vấn đề duy nhất là nó sẽ được sử dụng mặc nhiên, và đúc doesn không có ý nghĩa nhiều ở đây. Bạn cũng không thể phân biệt giữa các loại khác nhau của phôi (static_cast, c-phong cách, vv)

Đây là cách ưa thích để làm những việc:

struct square { 
    int get_area() const { 
    return (side * side); 
    } 
    int side; 
} 

Nếu bạn phải sử dụng một dàn diễn viên, sử dụng C++ 11 tính năng và đánh dấu nó explicit. Điều này ngăn chặn các lỗi đúc tiềm ẩn.