C ++中类型转换的条件

时间:2018-08-13 08:39:00

标签: c++ inheritance casting

我正在审查继承,并根据以下代码看到了 casting 的三个规则。 (来自https://www.youtube.com/watch?v=EYuPBkgJtCQ

class B{};
class D_priv: private B{};
class D_prot: protected B{};
class D_pub: public B{};

三个规则:

  1. 任何人都可以将D_pub*投射到B*D_pubB的一种特殊类型。
  2. D_priv的成员和朋友可以将D_priv*投射到B*
  3. D_prot的成员,朋友和孩子可以将D_prot*投射到B*

我对如何理解这三个规则感到非常困惑。 广播是否有一般条件? 成员朋友孩子是这里的意思吗?

我的问题主要是关于转换而不是继承。

1 个答案:

答案 0 :(得分:1)

为了能够从一个类转换为父类,父类的公共成员必须可用。更确切地说,在将子类上的公开成员调用给任何公开的成员时,父成员的公共成员必须是可调用的。

您可以问自己一个问题:如果我创建类型为B的对象,我可以调用D_prot的公共方法吗?如果答案是肯定的,那么您可以进行投射,例如:

class A
{
public:
    void foo();
};
class B : public A 
{
};
// Then when someone has a B object:
B b;
b.foo(); // Are we allowed to call foo()?
static_cast<A>(b).foo(); // If yes, we can cast it as well

更详尽的版本如下:

class Base
{
public:
    void foo() {} // Dummy method to clarify the example
};

class PublicChild : public Base
{
public:
    void test()
    {
        foo(); // OK, we have access to Base public members
        static_cast<Base*>(this)->foo(); // OK
    }
    friend class PublicFriend;
};

class PublicFriend
{
    void test(PublicChild* p)
    {
        p->foo(); // OK, the method is public anyway
        static_cast<Base*>(p)->foo(); // OK
    }
};

class ProtectedChild : protected Base
{
public:
    void test()
    {
        foo(); // OK, we have access to Base public members
        static_cast<Base*>(this)->foo(); // OK
    }
    friend class ProtectedFriend;
};

class ProtectedFriend
{
    void test(ProtectedChild* p)
    {
        p->foo(); // OK, because we are a friend of ProtectedChild, we have the same visibility as ProtectedChild itself
        static_cast<Base*>(p)->foo(); // OK
    }
};

class PrivateChild : private Base
{
public:
    void test()
    {
        foo(); // OK, we have access to Base public members
        static_cast<Base*>(this)->foo(); // OK
    }
    friend class PrivateFriend;
};

class PrivateFriend
{
    void test(PrivateChild* p)
    {
        p->foo(); // OK, because we are a friend of PrivateChild, we have the same visibility as PrivateChild itself
        static_cast<Base*>(p)->foo(); // OK
    }
};

int main()
{
    Base b;
    b.foo(); // OK: public method

    PublicChild p1;
    p1.foo(); // OK: public inheritance makes Base::foo public
    static_cast<Base>(p1).foo(); // OK

    ProtectedChild p2;
    p2.foo(); // error: protected inheritance makes Base::foo protected
    static_cast<Base>(p2).foo(); // error

    PrivateChild p3;
    p3.foo(); // error: private inheritance makes Base::foo private
    static_cast<Base>(p3).foo(); // error
}

示例:https://ideone.com/Zbaqbu

PS。在链接中,我对未编译的行进行了注释,可以随意添加代码并取消注释,以查看编译器的内容