2009-05-22 50 views
11

có ai biết tại sao điều này cho lỗi trình biên dịch không? Tôi cố gắng VS 2005 và CodeWarrior:Tham chiếu đến con trỏ và đa hình C++

class Parent { 
    protected: 
     int m_Var; 
    public: 
     Parent() : m_Var(0) {} 
     virtual ~Parent() {} 
     void PubFunc(); 
}; 

class Child : public Parent { 
    protected: 
     bool m_Bool; 
    public: 
     Child() : m_Bool(false) {} 
     virtual ~Child() {} 
     void ChildFunc(); 
}; 

void RemoveObj(Parent *& ppObj) 
{ 
    delete ppObj; 
    ppObj = 0; 
} 

int main() 
{ 
    Parent* pPObj = 0; 
    Child* pCObj = 0; 
    pPObj = new Parent(); 
    pCObj = new Child(); 

    RemoveObj(pPObj); 
    RemoveObj(pCObj); 
    return 1; 
} 

Visual studio nói:

refptr.cpp (33): lỗi C2664: 'RemoveObj': không thể chuyển đổi thông số 1 từ 'Child *' để 'Chánh * &'

Cảm ơn

Trả lời

16

tham số ppObj để RemoveOb j là một tham chiếu đến một Parent *. Điều gì sẽ xảy ra nếu phương pháp RemoveObj() thay thế con trỏ bằng một con trỏ đến đối tượng Parent mới? Khi phương thức trả về số pCObjChild* của bạn sẽ không trỏ đến đối tượng Child nữa.

+0

Lý do chính đáng. +1 :) –

4

Từ chuẩn C++ (1998)

Trừ trong bối cảnh của một khởi bởi, một tốt được hình thành chuyển đổi ngầm chuỗi người dùng định nghĩa chuyển đổi (13.3.1.4, 13.3.1.5) là một trong những hình thức sau: -a tiêu chuẩn chuyển đổi chuỗi (13.3.3.1.1), người sử dụng -a định nghĩa ...

13.3.3.1.1

Tại nhiều nhất một chuyển đổi từ mỗi thể loại được cho phép trong một đơn chuỗi chuyển đổi tiêu chuẩn

Vì vậy, C++ KHÔNG thể chuyển đổi ngầm hai lần liên tiếp: từ con trỏ đến con trỏ và sau đó một lần nữa từ con trỏ .

Để xóa này lên xem xét tuyên bố như vậy trong những RemoveObj

void RemoveObj(Parent ** ppObj) 

Và bạn sẽ thấy lỗi này

error: invalid conversion from 'Child**' to 'Parent**' 

Bạn phải sử dụng chuyển đổi rõ ràng như

RemoveObj((Parent**)&pCObj); 
    RemoveObj((Parent*&)&pCObj); 

hoặc có để thay đổi

void RemoveObj(Parent *& ppObj) 

để

void RemoveObj(Parent * ppObj) 

hoặc

template <typename T> 
void RemoveObj(T *& pObj) 
{ 
    delete pObj; 
    pObj = 0; 
} 
+0

Điều này không giải đáp được lý do tại sao nó là một lỗi complier, nhưng nó là những gì nó nên được thay đổi được. Các tham chiếu đến con trỏ là không cần thiết để làm những gì phương pháp đang làm. –

+0

Tôi đã thêm tham chiếu đến tiêu chuẩn. –

+0

Với chỉnh sửa, điều này chắc chắn là một câu trả lời là tại sao bạn nhận được một lỗi trình biên dịch. Bạn đang cố gắng chuyển đổi hai bước bất hợp pháp theo phần tiêu chuẩn @MykolaGolubyev đã chỉ ra. Thật không may, một 'reinterpret_cast' là giải pháp thiết thực nhất cho vấn đề này. –

-2

Đây không phải là thẩm quyền, nhưng tôi tin rằng vấn đề là tính chất đa hình của C++ lớp không mở rộng để con trỏ của họ; những gì bạn đang mong đợi để được thực hiện ở đây là cho một Child * để được đúc vào một Parent *; trong khi bạn có thể truyền Child đến Parent, bạn không thể truyền con trỏ tham chiếu. Đó là, các lớp có tính đa hình, nhưng các con trỏ tới các lớp không phải khi được lấy làm tham chiếu. Đây là lý do mà Michael Burr đưa ra ở trên; các Child * ngụ ý một cấu trúc bộ nhớ nhất định rằng Parent * không.

+3

chuyển đổi giữa các con trỏ là có thể. chuyển đổi tuy nhiên trả về một giá trị tạm thời. đó là lý do nó không thể được chuyển tới tham chiếu không phải const. –

+1

Vấn đề là từ tham chiếu, không phải là con trỏ. Bạn có thể chuyển các con trỏ thay thế cho nhau, nhưng không phải là một tham chiếu tới con trỏ của một con trỏ kiểu khác. –

+2

Tôi nghĩ rằng bạn đang nói về chuyển đổi của lvalues ​​để lvalues ​​w.r.t Child * để Parent *. Bạn đúng là một chuyển đổi như vậy là không thể. Nhưng bài đăng của bạn có vẻ như bạn đang ngụ ý rằng Child * to Parent * không được phép (nó không phải là). Không downvote, chỉ giúp bạn tìm ra lý do tại sao họ có thể downvoted bạn. (nếu họ chỉ nói với bạn ...) –

0

ppobj là tham chiếu cho con trỏ. * ppobj dereferences những gì biến trỏ đến, vì vậy bạn có được biến con trỏ.

Vì sự thiếu cân nhắc không đúng loại mà bạn gặp phải lỗi.

0

Con trỏ tới tham chiếu cho phép giá trị con trỏ thay đổi trong hàm. Như được ghi chú bởi Michael Burr, sẽ có khả năng gán một tham chiếu lớp không chính xác và trả lại nó. Hãy tưởng tượng toàn bộ chương trình của bạn không đúng cách sử dụng * pchickens như * peggs :)

Tôi nghĩ đó là giá trị bổ sung (mặc dù không rõ ràng những gì bạn hỏi): sở thích của tôi cho một việc thực hiện đa hình là để di chuyển các chức năng thông thường bên trong như một phương pháp. Nếu tất cả đều chia sẻ một hàm, hãy thêm nó vào lớp cơ sở.

Sau đó, bạn có thể gọi Foo-> Bar() và đạt được kết quả mong muốn. Nhưng đối với ví dụ triển khai cụ thể mà bạn đưa ra, chỉ cần xóa Foo sẽ gọi hàm hủy phù hợp.

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