派生类向基类转换的可访问性

来源:互联网 发布:低功率电热水壶 知乎 编辑:程序博客网 时间:2024/06/11 11:19

最近写程序时遇到了一个问题,涉及到了派生类向基类转换的可访问性,也就是带有访问控制标号的继承,以前没有注意到这块知识,给自己挖了个坑,现在写出来,当是一次总结,也希望能帮到遇到类似问题的人。

先说我遇到的问题吧,直接用代码说:

class ProblemBase{};class ProblemD : private ProblemBase{};class ProblemDD : private ProblemD{public:    ProblemBase& getProblemBase()    {        return static_cast<ProblemBase&>(*this);    }};int main(){}


上面的代码无法通过编译,提示‘class ProblemBase ProblemBase :ProblemBase‘ is inaccessible。把calss ProbelmD : private  ProblemBase中的private改为public后,能够通过编译。或者把static_cast那行注掉也能通过编译。这就说明问题就出在这个转换上。于是查询了一下工具书,发现书中有讲到(知识盲点)。

C++ primaer(第五版)》里有这样一段话:

派生类向基类的转换是否可访问由使用该转换的代码决定,同时派生类的派生访问说明符也会有影响。假定D继承自B:

1.只有当D公有地继承B时,用户代码才能使用派生类向基类的转换;如果D继承B的方式是受保护的或者私有的,则用户代码

不能使用该转换。

2.不论D以什么方式继承B,D的成员函数和友元都能使用派生类向基类的转换;派生类向其直接基类的类型转换对于派生类的

成员和友元来说永远是可访问的。

3.如果D继承B的方式是受保护的或者公有的,则D的派生类的成员和友元可以使用D向B的类型转换;反之,如果D继承B的方式是私有的,

则不能使用。

总之,对于代码中的某个给定节点来说,如果基类的公有成员是可访问的,则派生类向基类的类型转换也是可访问的;反之则不行。



感觉上述代码其实并没有直接印证在以上三点,下面我们先通过测试代码来证明以上三点,在代码测试中讲述我的出错代码时如何印证在上面的。
class B{};class DPubB : public B{public:    B& getB()    {        return static_cast<B&>(*this); //公有继承,类代码可以使用转换    }};class DProB : protected B{public:        B& getB()    {        return static_cast<B&>(*this); //虽然是受保护继承,但是类代码仍使用转换,印证2    }};class DPriB : private B{public:    B& getB()    {        return static_cast<B&>(*this); //虽然是私有继承,但是类代码仍使用转换,印证2    }};class DD1 : public DPriB{    //B& getBFrom_DPriB()    //{    //    return static_cast<B&>(static_cast<DPriB&>(*this)); //DD1先转换为DPriB,再由DPriB转换为B时由于3不能完成转换    //}    //B& getBFromDD1()    //{    //    return static_cast<B&>(*this); //DD1直接转换为B,为了便于可以分解为上面两步,也不能完成转换    //}    };class DD2 : private DProB{public:    B& getBFrom_DProB()    {        return static_cast<B&>(static_cast<DProB&>(*this)); //DD2先转换位DPriB,再由DPriB转换为B时由于3能够完成转换    }    B& getB1From_DD2()    {        return static_cast<B&>(*this); //DD2直接转换为B,为了便于可以分解为上面两步,也能够完成转换    } };int main(){    B* b1 = new DPubB();    //B* b2 = new DProB();    //B* b3 = new DPriB(); //用户代码不能使用私有、受保护继承的转换,印证1}


经过上述代码,我们可以发现,其实我遇到的问题就是DD1。


当出现B:A, C:B时根据继承标号有9种情况,而我们只讨论了2种,其实足够了。因为public继承都不可以转换,private,protected继承更不可以;private能够转换,protected,public更能转换。讨论了两种,其实已经涵盖了9种。


好了,派生类向基类转换的可访问性,就讨论到这里,希望能对你有所帮助。

0 0