2016-11-09 18 views
9

Giả sử tôi có hai lớp. Một gọi là Point:Cấp độ truy cập lớp C++

class Point{ 
    public: 
     Point(): x_(0), y_(0) {} 
    protected: 
     int x_, y_; 
    }; 

Sau đó, tôi có một lớp, mà xuất phát từ Point:

class Point3D : public Point { 
public: 
    Point3D(): Point(), z_(0){} 
    double distance(Point3D pt, Point base) const; 
protected: 
    int z_; 
}; 

double Point3D::distance(Point3D pt, Point base) const 
{ 
    int dist_x, dist_y; 
    dist_x = base.x_ - x_; 
    dist_y = base.y_ - y_; 

    return sqrt(dist_x * dist_x + 
       dist_y * dist_y); 
} 

Sau đó, tôi đã nhận lỗi như: base.x_ được bảo vệ trong bối cảnh này. Nhưng mức truy cập của Point3D to Point là công khai, cộng với thành viên dữ liệu x_ trong Point được bảo vệ. Vì vậy, nó được cho là không có lỗi, phải không? Ai đó có thể giúp tôi làm rõ điều này không?

+0

Btw., Bạn có nên sử dụng pt thay vì điều này hay xóa tham số pt không? – deviantfan

+0

@deviantfan oh quên thông số đầu vào pt. –

Trả lời

1

Chế độ kế thừa công khai chỉ đơn giản có nghĩa là đối tượng có thể truy cập các thành viên được bảo vệ của lớp cơ sở của nó. Trong ví dụ này, mọi đối tượng Point3D chỉ có thể truy cập các thành viên x_y_ của các đối tượng Point3D.

Tuy nhiên, điều này không cho phép đối tượng truy cập các thành viên được bảo vệ khác của Điểm từ lớp cơ sở.

EDIT: Như được chỉ ra bởi J. Lin, chỉ cần thay đổi loại cơ sở từ Point thành Point3D cho phép chức năng thành viên truy cập x_y_.

+1

Tôi nghĩ nếu bạn thay đổi loại cơ sở từ Point thành Point3D, mã sẽ hoạt động tốt. –

6

Nhưng mức độ tiếp cận của Point3D-Pointpublic

Đó không phải là hoàn toàn đúng. Các thành viên được bảo vệ của một lớp cơ sở có thể truy cập đến một lớp dẫn xuất chỉ khi chúng được truy cập thông qua một con trỏ lớp/tham chiếu có nguồn gốc.

double Point3D::distance(Point3D pt, Point base) const 
{ 
    int dist_x, dist_y; 
    dist_x = base.x_ - x_; // x_ is same as this->x_. Hence it is OK. 
          // base is not a Point3D. Hence base.x_ is not OK. 
    dist_y = base.y_ - y_; 

    return sqrt(dist_x * dist_x + 
       dist_y * dist_y); 
} 

Cho phép truy cập vào protected thành viên của một lớp cơ sở thông qua một con trỏ lớp cơ sở/tài liệu tham khảo sẽ cho phép bạn thay đổi các đối tượng trong cách mà sẽ dẫn đến hậu quả không lường.

Giả sử bạn có:

class Base 
{ 
    protected: 
    int data; 
}; 

class Derived1 : public Base 
{ 
    void foo(Base& b) 
    { 
     b.data = 10; // Not OK. If this were OK ... what would happen? 
    } 
}; 

class Derived2 : public Base 
{ 
}; 

int main() 
{ 
    Derived1 d1; 
    Derived2 d2; 
    d1.foo(d2); 
} 

Nếu

 b.data = 10; 

đã được cho phép trong Derived1::foo, bạn có thể sửa đổi trạng thái của d2, một thể hiện của Derived2 bởi Derived1. Đó là loại sửa đổi backdoor không phải là một hành vi mong muốn.

+1

Thx để trả lời. Nhưng nếu bạn thay đổi base.x và base.y thành pt.x và pt.y, mã hoạt động tốt. Và cá thể lớp dẫn xuất pt đang truy cập các thành viên lớp cơ sở được bảo vệ mà không sử dụng điểm/tham chiếu, điều này có thể mâu thuẫn với đối số của bạn. Tôi có hiểu nhầm ý tưởng của bạn không? –

+0

@ J.Lin, 'pt.x' là ok vì' pt' là đối tượng của loại 'Point3D'. Số tiền đó để truy cập vào một thành viên 'protected' của lớp cơ sở bằng cách sử dụng một tham chiếu đến một đối tượng của kiểu lớp dẫn xuất. –

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