2016-11-09 55 views
9

假設我有兩個類。一個叫點:C++類訪問級別

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

然後,我有另一個類,它派生點:

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); 
} 

然後我得到了像錯誤:base.x_在此範圍內的保護。但是Point3D對Point的訪問級別是公共的,並且Point中的x_數據成員被保護。所以它應該是沒有錯誤的,對吧?有人可以幫我解決這個問題嗎?

+0

順便說一句,你不應該使用pt代替這個,或者刪除參數pt? – deviantfan

+0

@deviantfan哦忘記輸入參數pt。 –

回答

1

公共繼承模式只是意味着對象可以訪問其基類的受保護成員。在本例中,每個Point3D對象只能訪問Point3D對象的x_y_成員。

但是,這不允許該對象從其基類訪問另一個Point的受保護成員。

編輯:正如J.林指出的,只需改變基點類型從點到點3D允許成員函數訪問x_y_

+1

我想如果你改變點到Point3D的基地類型,代碼將正常工作。 –

6

Point3DPoint訪問級別是public

這是不完全正確的。僅當通過派生類指針/引用訪問基類時,才能訪問派生類的受保護成員。

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); 
} 

允許通過一個基類指針訪問基類的成員protected /參考將允許你改變的方式,這將導致意想不到的後果對象。

假設你有:

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); 
} 

如果

 b.data = 10; 

Derived1::foo被允許,您可以通過Derived1修改的d2的狀態下,Derived2一個實例。這種後門修改不是一種理想的行爲。

+1

Thx的答覆。但是,如果您將base.x和base.y更改爲pt.x和pt.y,則代碼可以正常工作。派生類實例pt正在訪問受保護的基類成員,而不使用point/reference,這可能與您的論點相矛盾。我誤解了你的想法嗎? –

+0

@ J.Lin,'pt.x'可以,因爲'pt'是類型爲'Point3D'的對象。這相當於使用對派生類類型的對象的引用來訪問基類的「受保護」成員。 –