如何判断derived-to-base conversion是否legal
我們知道,在類內的access specifier public 、protected、private都只是為了限定用戶程序對類內的訪問權限,而在繼承list中的access specifier則是影響使用該derived類的用戶對該類內的訪問權限。public繼承延續base部分的access specifier;protected繼承則是把base public部分變成了protected,其余不變;private繼承則是把所有base部分變成private。具體可以看primer p612 613的例子(english version)。
對于判斷derived-to-base conversion是否legal,最重要的是該derived指針或base指針是否可以訪問到base類中的public成員。這個準則實際上是為了保證讓轉換后的base指針可以像其他普通base指針一樣可以訪問應該可以訪問得到的成員。這個判斷準測與primer p613下面提出的3點是相匹配的。stackoverflow上有對此的討論,我們結合它上面的代碼來驗證這個判斷準則。
注意看注釋!注釋!注釋!重要的事情說三遍...
1 class B; 2 class C; 3 class D; 4 class A{ 5 public: 6 virtual ~A(){} 7 friend void gg(D* d); 8 void ga(B *b,C* c,D* d); int mem; 9 }; 10 11 class B:protected A{ 12 public: 13 void gb(B *b,C* c,D* d); 14 }; 15 class C:public B{}; 16 class D:public C{}; 17 18 void A::ga(B *b,C*c,D*d){ 19 A *a1=b; // error: 'A' is an inaccessible base of 'B' 原因:在A類中B類指針b無法訪問base A部分的成員,即這里的b->mem是非法的(B是protected繼承A),所以也就不能轉換。 20 A *a2=c; // error: 'A' is an inaccessible base of 'C' 原因同上,這里的c->mem也是非法的,因為mem在C類中是protected的。 21 A *a3=d; // error: 'A' is an inaccessible base of 'D' 原因同上。 22 } 23 void B::gb(B *b,C*c,D*d){ 24 A *a1=b; // no problem here ,這里沒問題是因為在類B中,b->mem是合法的。 25 A *a2=c; //why do classes derived from B can sucessfully convert to A here? 這里c->mem是非法的,只有在類C或friend of class c中c->mem才合法。 26 A *a3=d; //why do classes derived from B can sucessfully convert to A here? 原因同上 27 } 28 void gg(D* d){ 29 A* a=d; // 這里也會報錯,同上 30 } 31 int main(){ 32 B b; 33 C c; 34 D d; 35 A a; 36 gg(&d); // error: 'A' is an inaccessible base of 'D' 37 a.ga(&b,&c,&d); 38 b.gb(&b,&c,&d); 39 A a1(d); //error here;Does it mean the implicit conversion in the user code is also user code? 40 A a4=d; //same as above 41 return 0; 42 }但是,下面那個例子打破了這個準則,問題在http://stackoverflow.com/questions/30524479/what-is-the-rationale-for-allowing-this-derived-to-base-conversion-when-it-seem 上。 根據里面的解釋,我認為準則應該再加上primer中p614最頂端的那個條件:
member functions and friends of classes derived from D may use the d-to-b conversion if D inherits from B using either public or protected. Such code may not use the conversion if D inherits privately from B.
這就可以很好地解釋下面那段代碼了。
1 class Base 2 { 3 public: 4 int mem; 5 }; 6 7 class Derived : protected Base 8 { 9 static void f(Derived *d) 10 { 11 d->mem; // OK, in this context, a Derived IS-A Base 12 Base *b = d; 13 } 14 }; 15 16 int main() 17 { 18 Derived d; 19 //d.mem; // Compilation error : in this context a Derived IS-NOT-A Base 20 //Base *b = &d; // Compilation error too : consistent with the intuitive rule 21 return 0; 22 } 23 24 class Derived_Derived : public Derived 25 { 26 static void f(Derived *d) 27 { 28 //d->mem; // Compilation error : in this context a Derived IS-NOT-A Base (as expected) 29 Base *b = d; // COMPILATION OK : which seems to violate the rule above 30 } 31 };?
轉載于:https://www.cnblogs.com/weili-wu/p/4861277.html
總結
以上是生活随笔為你收集整理的如何判断derived-to-base conversion是否legal的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C# 之 获取文件名及拓展名
- 下一篇: Redis详解——常用命令总结(完善中)