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

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

  • 只有当D公有继承B时,用户代码才能使用派生类向基类到转换;如果D继承B的方式时受保护的或者私有的,则用户代码不能使用该转换。
  • 不论D以什么方式继承B,D的成员函数和友员函数都能使用派生类向基类的转换;派生类向其直接基类的类型转换对于派生类的成员和友员而言永远是可访问的。
  • 如果D继承B 的方式是公有的或者受保护的,则D的派生类的成员和友员可以使用D向B 的类型转换;反之,如果D继承B 的方式时私有的,则不能使用

    上买的定义是摘自c++Primer 里面的定义,听起来是不是很绕口,所以下面就结合代码通俗的解释下:

先看第一问吧,是什么意思,定义三个类如下

#include <iostream>
#define _COUT(str) std::cout<<str<<" ";
#define _COUTL(str) std::cout<<str<<std::endl;

class A{
public:
    virtual void print()
    {
        _COUTL("我是A");
    }
};

class B :public A
{
public:
    void print()
    {
        _COUTL("我是B 继承A");
    }
};

class C : private A
{
public:
    void print()
    {
        _COUTL("我是C 继承A");
    }

};

int main()
{
    A *p;
    B b;
    C c;
    
    p = &b;
    p = &c;// error:Cannot cast 'C' to its private base class 'A'
    p->print();
    
}

也就是说A 的派生类C无法转换为A因为C是私有继承A 的,而B向A 的转换成功了,没有什么问题,至于为什么A要用指针那就是虚函数的问题了,详情看其他文章吧,这里就不多说了。

接下来是第二问:

不论D以什么方式继承B,D的成员函数和友员函数都能使用派生类向基类的转换;派生类向其直接基类的类型转换对于派生类的成员和友员而言永远是可访问的。 这里就在定义四个类 分别继承B(D只是代表,代码中就不严格根据了,同时,为了方便起见,函数的定义全部放在类的内部,自动内联-0-)

class B{
};
class D:public B{
    void function(D &d){
        B b = d;
    }
    friend void friendFunction(D &d)
    {
        B b = d;
    }
};
class E:protected B{
    void function(E &e){
        B b = e;
    }
    friend void friendFunction(E &e)
    {
        B b = e;
    }
};
class F:private B{
    void function(F &f){
        B b = f;
    }
    friend void friendFunction(F &f)
    {
        B b = f;
    }
};

大家可以讲代码拷贝到编译器之中,发现都没有报错,看了代码也应该理解第二句话的意思了。

最后是第三句话:

如果D继承B 的方式是公有的或者受保护的,则D的派生类的成员和友员可以使用D向B 的类型转换;反之,如果D继承B 的方式时私有的,则不能使用。这句话咋一看和第二句没什么区别....可一定注意!!是D的派生类。

class D:public B{
    void function(D &d){
        B b = d;
    }
    friend void friendFunction(D &d)
    {
        B b = d;
    }
};
class E:protected B{
    void function(E &e){
        B b = e;
    }
    friend void friendFunction(E &e)
    {
        B b = e;
    }
};
class F:private B{
    void function(F &f){
        B b = f;
    }
    friend void friendFunction(F &f)
    {
        B b = f;
    }
};
class G : D{
    void function(D &d){
        B b = d;
    }
};

class H : E{
    void function(E &e){
        B b = e;
    }
};

class I : F{
    void function(F &d){
        B b = f; //error:'B' is a private member of 'B'
    }
    friend void friendFunction2(F &f)
    {
        B b = f; //error:'B' is a private member of 'B'
    }
};

上述DEF分别公有、保护、私有继承B,而 GHI 分别继承DEF。可见只有I报错,因此可得出结论三。

猜你喜欢

转载自blog.csdn.net/monster_acm/article/details/81200777