2010-09-09 27 views
19

Đây là mã của tôi -Tại sao chuyển đổi giữa xuất phát * thành cơ sở * không thành công với kế thừa riêng?

#include<iostream> 
using namespace std; 

class base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

class derived : private base 
{ 
public: 
    void sid() 
    { 
    } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived' 
    ptr->sid(); 
    return 0; 
} 

Điều này tạo ra lỗi thời gian biên dịch.

error: 'base' is an inaccessible base of 'derived' 

Vì trình biên dịch sẽ thử gọi lớp cơ sở sid() tại sao tôi gặp lỗi này? Ai đó có thể giải thích điều này.

+0

Bạn không khai báo phương thức 'virtual'. Lỗi nào là bạn đang nhận được chính xác? – Dirk

+8

Ở dạng hiện tại, nó không liên quan gì đến hàm 'sid()'. Bạn đang sử dụng thừa kế riêng do đó việc chuyển đổi từ 'origin *' sang 'base *' là không thành công. Có phải đó là những gì bạn đang yêu cầu hoặc nó là một cái gì đó để làm với phương pháp 'sid()'? – Naveen

+1

có thể trùng lặp của [Lớp được bảo vệ có nguồn gốc] (http://stackoverflow.com/questions/433965/protected-derived-class) – kennytm

Trả lời

16

$ 11,2/4 states-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

đây 'B' là 'cơ sở', 'N' là 'nguồn gốc' và 'R' là chính.

  1. Hãy xem trường hợp thứ hai 'R xảy ra ở thành viên hoặc bạn của lớp N, ...'. Mệnh đề này không áp dụng là 'R' (chính) không phải là thành viên cũng không phải là bạn của 'N' (Có nguồn gốc)

  2. Xem xét viên đạn thứ 3 'xảy ra trong thành viên hoặc bạn của lớp P ... . '. claus này cũng không áp dụng vì những lý do tương tự như trên

  3. Hãy xem xét chống đạn thứ 4 Một lần nữa điều khoản này không áp dụng

Như vậy chúng ta có thể kết luận rằng 'cơ sở' không phải là một lớp truy cập của 'Nguồn gốc'.

$ 11,2/5 bang -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

Kể từ Base không phải là một lớp truy cập của Derived khi truy cập trong main, việc chuyển đổi tiêu chuẩn từ lớp Derived đến lớp Base là vô hình thành. Do đó lỗi.

CHỈNH SỬA 2:

Nghiên cứu thông báo lỗi của một số trình biên dịch phổ biến và điều đó sẽ giúp bạn hiểu rõ hơn.Lưu ý cách từ 'không thể truy cập' bật lên thường xuyên và nhất quán trên tất cả các thông báo lỗi

Tham chiếu đến từ bản nháp tiêu chuẩn N3000. Tôi chưa tải xuống bản nháp mới nhất :)

GCC prog.cpp: In function ‘int main()’: prog.cpp:27: error: ‘base’ is an inaccessible base of ‘derived’

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

+0

Bạn có thể vui lòng cung cấp tham chiếu của mình không. – Bruce

+0

@Bruce: Oh xin lỗi, tôi quên đề cập đến rằng các tài liệu tham khảo là từ dự thảo tiêu chuẩn N3000. Tôi thấy rằng C++ 03 có một số câu khó hiểu để hiểu khái niệm này. Tôi sẽ cập nhật bài đăng của mình cho phù hợp – Chubsdad

+0

Xem câu trả lời của Douglas Leeder và ereOn về các giải pháp dễ đọc và nhanh chóng của con người. – mwjohnson

35

Tôi nghi ngờ vấn đề là bạn không thể chuyển đổi một con trỏ có nguồn gốc thành con trỏ cơ sở, vì thừa kế là riêng tư.

+0

Tại sao tôi không thể làm điều này? Các vấn đề triển khai trong vấn đề này là gì? – Bruce

+2

Kế thừa riêng có nghĩa là bạn không muốn giao diện lớp cơ sở có thể truy cập được mã khác so với mã lớp con. – Klaim

+7

Không thực sự cảm thấy muốn dành thời gian giải thích câu trả lời của Chubsdad và đây chính là điều tôi cần biết. Đã thiếu một tuyên bố 'public' trên định nghĩa lớp dẫn xuất của tôi – User

0

Bạn cần khai báo hàm sid() của bạn trong lớp cơ sở là ảo. Một hàm ảo có thể được thay thế bằng một lớp dẫn xuất. Nếu không, bạn có thể sẽ gặp lỗi trình biên dịch.

+4

Bạn biết đấy, tôi ghét nó khi mọi người downvote, và không để lại một bình luận. –

+0

Tôi đã không bỏ phiếu cho câu trả lời này, nhưng tôi nghĩ nó bị nhầm lẫn. Tôi đã nhìn thấy trình biên dịch cung cấp cho * cảnh báo * để ẩn một hàm cơ sở lớp với một lớp dẫn xuất, nhưng không bao giờ là một lỗi. –

5

Hãy thử điều này:

#include<iostream> 
#include<conio.h> 
using namespace std; 

class base 
{ 
     private: 
     public: 
      virtual void sid() // You might want to declare sid virtual 
      { 
        cout<<"base"; 
      } 
      virtual ~base() // You then probably need a virtual destructor as well. 
      { 
      } 
}; 

class derived : public base //public inheritance 
{ 
     private: 
     public: 
      void sid() 
      { 
        cout<<"derived"; 
      } 
}; 

int main() 
{ 
    base * ptr; 
    ptr = new derived; 
    ptr->sid(); 
    getch(); 
    return 0; 
} 
+0

Bạn có nghĩa là 'ảo void sid()'? Ngoài ra, bạn cần destructor lớp cơ sở là 'virtual'. – Naveen

+0

@Naveen: Cảm ơn. Tôi đã trên con đường của tôi để thêm destructor;) Ngoài ra có, 'tư nhân' là một lỗi đánh máy. – ereOn

+0

Trình phá hủy ảo là một ý tưởng hay. Đặt ảo trên chức năng sid là trái với một mục tiêu đã nêu của poster gốc. –

6

Bạn biết rằng class derived thừa hưởng từ class base, nhưng main() chức năng không biết điều đó. Lý do hàm main() không biết rằng bạn đã thực hiện class derived kế thừa PRIVATELY từ class base.

Do đó khi bạn cố gắng gán new derived đến ptr, loại con trỏ không tương thích.

+0

@WP: Bạn có thể vui lòng xây dựng trên câu trả lời của bạn – Bruce

+0

Chubsdad đã làm ... –

8

Chusbad cung cấp giải thích chi tiết liên quan đến tiêu chuẩn, tôi sẽ cố gắng cung cấp giải thích có thể truy cập.

Trong C++, có 3 thông số cấp truy cập: public, protectedprivate. Đó là để xác định WHO có thể truy cập các phương thức, thuộc tính hoặc các lớp cơ sở. Nó là điển hình trong số các ngôn ngữ hướng đối tượng.

Tại đây, bạn đã chọn private kế thừa. Khái niệm này có nghĩa là bạn tìm cách ẩn một thực tế là Derived kế thừa từ Base cho người ngoài, thường có nghĩa là đây là một chi tiết thực hiện.

Kết quả là, "bên ngoài" không biết mối quan hệ này. Điều này được thực thi bởi trình biên dịch với thông báo inaccessible này.

Từ quan điểm thiết kế, private thừa kế thường không được yêu cầu. Nguyên tắc thay thế Liskov áp dụng và bạn sử dụng thừa kế public, hoặc là chi tiết triển khai và bạn sử dụng bố cục.

0

điều này cho lỗi C2243: 'loại diễn viên': chuyển đổi từ 'có nguồn gốc *' thành 'cơ sở *' tồn tại, nhưng không thể truy cập được Lớp dẫn xuất này đã được thừa hưởng riêng .so đối tượng lớp cơ sở không được tạo khi nhận được sáng tạo xảy ra. để tạo ra các đối tượng dẫn xuất, các cuộc gọi đầu tiên sẽ tạo ra đối tượng lớp cơ sở không xảy ra. soltuion là để lấy được các lớp công khai. nó không quan trọng cho dù bạn sử dụng từ khóa ảo có chức năng thành viên hay không.

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