2011-01-28 49 views

Trả lời

5

Vì mã sẽ sử dụng giá trị trả về như thế nào đối phó với tất cả các loại loại không liên quan sắp trở lại? ví dụ .:

class A 
{ 
public: 
    virtual float func(); 
}; 

class B: public A 
{ 
public: 
    virtual char *func(); 
}; 

A *p = (some_condition) ? new A() : new B(); 
p->func(); // Oh no! What is the type? 
+0

Có, loại không liên quan = xấu. Còn các loại liên quan khác thì sao? – curiousguy

13

Do vô nghĩa đó sẽ xảy ra sau:

struct foo 
{ 
    virtual int get() const { return 0; } 
}; 

struct bar : foo 
{ 
    std::string get() const { return "this certainly isn't an int"; } 
}; 

int main() 
{ 
    bar b; 
    foo* f = &b; 

    int result = f->get(); // int, right? ...right? 
} 

Nó không phải là hợp lý để có một xuất phát trở lại một cái gì đó hoàn toàn không liên quan lớp.

+0

Thảo luận [chuyển sang trò chuyện.] (Http://chat.stackoverflow.com/rooms/15288/discussion-between-gmannickg-and-curiousguy) – GManNickG

+0

Kết luận của cuộc trò chuyện: ** GManNickG thừa nhận rằng quy tắc C++ hiện tại chỉ cho phép con trỏ (hoặc tài liệu tham khảo) có thể được thoải mái. ** – curiousguy

+0

Không phải là một "thừa nhận", tôi không bao giờ phủ nhận nó ở nơi đầu tiên ... – GManNickG

3

Theo C++ Standard:

Kiểu trả về của một chức năng quan trọng hơn sẽ là một trong hai giống với kiểu trả về của các ghi đè func- tion hoặc hiệp biến với các lớp học của các chức năng. Nếu một hàm D :: f ghi đè một chức năng B :: f, các loại trở lại của các chức năng là hiệp biến nếu họ đáp ứng các tiêu chí sau:

1) cả hai đều là con trỏ đến các lớp học hoặc tham chiếu đến các lớp học

2) lớp trong kiểu trả về của B :: f là cùng một lớp với lớp trong kiểu trả về của D :: f, hoặc là một lớp cơ sở trực tiếp hoặc gián tiếp có thể truy cập hoặc gián tiếp của lớp trong loại trả về của D :: f

3) cả hai con trỏ hoặc tham chiếu es có cùng trình độ cv và loại lớp trong kiểu trả về của D :: f có cùng trình độ cv bằng hoặc ít cv-qualification hơn loại lớp trong kiểu trả về của B :: f.

+1

Câu hỏi đã cho thấy hạn chế, nó hỏi tại sao hạn chế này tồn tại. – GManNickG

1

Câu trả lời rất giống với câu trả lời cho "Why can't I assign a vector<Apple*> to a vector<Fruit*>?" về Câu hỏi thường gặp của Bjarne Stroustrup.

Khả năng sửa đổi loại trả về sẽ dẫn đến lỗ hổng trong loại an toàn của ngôn ngữ (xem câu trả lời từ @GManNickG để biết ví dụ cụ thể) khi xử lý các loại đa hình.

Có một tình huống khá phổ biến khi ảnh hưởng đến kiểu trả về sẽ là lý tưởng: khi trả về một con trỏ đa hình từ một phương thức ảo của một kiểu cơ sở. Ví dụ:

class Base { 
public: 
    virtual Base* parent() = 0; 
}; 

class Child : public Base { 
public: 
    Base* parent() override 
    { 
     return parent_; 
    } 
private: 
    Parent* parent_; // Assume `Parent` type exists. 
}; 

Ở đây chúng tôi đã mất thông tin loại Child biết về thành viên parent_. Điều này dẫn đến rất nhiều đúc, mặc dù loại đã được tại một điểm cũng được xác định. Chúng tôi có thể giải quyết vấn đề này bằng cách sử dụng thành ngữ Curiously Recurring Template Parameter (CRTP),

template<class ParentType> 
class Base { 
public: 
    virtual ParentType* parent() 
    { 
     return parent_; 
    } 

private: 
    ParentType* parent_; 

}; 

class Child : public Base<Parent> { 
}; 
+0

"_Câu trả lời rất giống với câu trả lời cho" Tại sao tôi không thể gán một vector cho một véc tơ ? "Trên Câu hỏi thường gặp của Bjarne Stroustrup._" Nó không giống bất kỳ cách nào. "_ Khả năng sửa đổi kiểu trả về sẽ dẫn đến một lỗ hổng trong kiểu an toàn của ngôn ngữ_" Khả năng sửa đổi kiểu trả về ** mà không có bất kỳ ràng buộc nào ** rõ ràng là không an toàn. Điều đó không trả lời câu hỏi ban đầu "tại sao chúng ta có ** hạn chế này **?" không phải "tại sao chúng ta có bất kỳ hạn chế nào?" – curiousguy

Các vấn đề liên quan