如何判断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 };
时间: 2024-11-05 06:25:09

如何判断derived-to-base conversion是否legal的相关文章

NUMBER BASE CONVERSION(进制转换)

Description Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits: { 0-9,A-Z,a-z } HINT: If you make a sequence of base conversions using the output of one conversion as the input to the next, when

Base Conversion In PHP and javascript

http://www.exploringbinary.com/base-conversion-in-php-using-built-in-functions/ http://www.binaryconvert.com/convert_float.html?decimal=054046056050049051 https://www.codeproject.com/Tips/387989/Convert-Binary-Single-Precision-Value-to-Float-in funct

POJ 1220 NUMBER BASE CONVERSION 高精度进制转换

      poj  50题拍照合影留念 NUMBER BASE CONVERSION Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 4620   Accepted: 2115 Description Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits: { 0-

[POJ1220]NUMBER BASE CONVERSION (高精,进制转换)

题意 任意进制之间的高进的转换 思路 相模倒排,高精处理 代码 我太弱了,下面附一个讨论里发的maigo思路的代码 int i,l,k,a,b,T,t[555],A[555]; char s[555],d[555]; main(){ for(scanf("%d",&T);T--;){ scanf("%d%d%s",&a,&b,s); for(k=i=strlen(s);0<i--;)t[k-1-i]=s[i]-(s[i]<58?4

【C++11学习笔记】类型判断的type_traits学习

一.简单的type_traits 我理解的type_traits是利用C++模板特性和static.enum特性定义编译器常量,例如 //std::integral_constant源码 typelate<class T, T v> struct integral_constant { static const T value = v; typedef T value_type; typedef integral_constant<T, v> type; operator valu

Java 中的泛型详解-Java编程思想

Java中的泛型参考了C++的模板,Java的界限是Java泛型的局限. 2.简单泛型 促成泛型出现最引人注目的一个原因就是为了创造容器类. 首先看一个只能持有单个对象的类,这个类可以明确指定其持有的对象的类型 class Holder1 { private Circle a; public Holder1(Circle a) { this.a = a; } Circle get() { return a; } } 上面的类的可重用性不怎么样,无法持有其他类型的任何对象,下面通过持有Object

Java编程思想读书笔记

声明:原创作品,转载时请注明文章来自SAP师太技术博客:www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将追究法律责任!原文链接:http://www.cnblogs.com/jiangzhengjun/p/4290955.html 第一章对象导论... 1 第二章一切都是对象... 4 第三章操作符... 10 第四章流程控制... 12 第五章初始化与清理... 14 第六章访问权限控制... 15 第七章复用... 23 第八章多态... 2

Google C++ 代码规范

Google C++ Style Guide Table of Contents Header Files Self-contained Headers The #define Guard Forward Declarations Inline Functions Names and Order of Includes Scoping Namespaces Unnamed Namespaces and Static Variables Nonmember, Static Member, and

GoogleCpp风格指南 3)类

3 类 Classes 类是C++中代码的基本单元; 显然, 它们被广泛使用; 本节列举了写一个类时的主要注意事项; 3.1 构造函数的职责 Doing Work in Constructors Tip 构造函数中只进行那些没什么意义的(trivial 译注: 简单初始化对于程序执行没有实际的逻辑意义, 因为成员变量"有意义"的值大多不再构造函数中确定)初始化, 可能的话, 使用 Init()方法集中初始化有意义的(non-trival)数据; [Add] 在ctor中防止做复杂的初始