You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

派生类地址赋值基类指针编译报错:访问说明符作用解析

正常编译案例
#include <iostream>
#include <sstream>
using namespace std;

class A{
    public:
    A(){
        cout << "A" << endl;
    }
    
    virtual void foo()
    {
        cout << "A' foo" << endl;
    }
};

class B{
    public:
    B(){
        cout << "B" << endl;
    }
    
    virtual void foo()
    {
        cout << "B' foo" << endl;
    }
};

class C{
    public:
    C(){
        cout << "C" << endl;
    }
    
    virtual void foo()
    {
        cout << "C' foo" << endl;
    }
};

class D : public B,A,C{
    public:
    D(){
        cout << "D" << endl;
    }
    
    void foo()
    {
        cout << "D' foo" << endl;
        A::foo();
    }
};

int main()
{
    class B*ptr = new D;
    return 0;
}
编译报错案例

A是D的基类,但为何编译器不允许将派生类地址赋值给基类指针?

int main()
{
    class A*ptr = new D;
    return 0;
}

输出:error: ‘A’ is an inaccessible base of ‘D’

始终正常编译案例

为每个基类指定访问说明符后即可正常编译:

#include <iostream>
#include <sstream>
using namespace std;

class A{
    public:
    A(){
        cout << "A" << endl;
    }
    
    virtual void foo()
    {
        cout << "A' foo" << endl;
    }
};

class B{
    public:
    B(){
        cout << "B" << endl;
    }
    
    virtual void foo()
    {
        cout << "B' foo" << endl;
    }
};

class C{
    public:
    C(){
        cout << "C" << endl;
    }
    
    virtual void foo()
    {
        cout << "C' foo" << endl;
    }
};

class D : public B, public A, public C{
    public:
    D(){
        cout << "D" << endl;
    }
    
    void foo()
    {
        cout << "D' foo" << endl;
        A::foo();
    }
};

int main()
{
    class A*ptr = new D;
    return 0;
}

多继承场景下访问说明符的工作机制

在C++中,用class关键字定义派生类时,如果没有显式指定基类的访问说明符,编译器会默认使用private继承(如果是struct定义的类,默认则是public继承)。

结合你的案例拆解:

  1. 第一个场景里class D : public B,A,C,B被显式声明为public继承,而A和C没有指定访问说明符,所以默认是private继承:
    • public继承的B:外部代码可以把D*隐式转换为B*,因为B是D的可访问基类,这也是第一个案例能正常编译的原因。
    • private继承的A、C:基类的继承关系对外部代码隐藏,外部无法将D*转换为A*或C*,这就是第二个案例报错“A是不可访问基类”的核心原因。
  2. 第三个场景里class D : public B, public A, public C,所有基类都显式指定了public继承:
    • 此时A、B、C都是D的可访问基类,外部代码可以自由将D*转换为任意基类指针,因此编译正常。

额外补充几个关键细节:

  • 访问说明符本质控制的是基类在派生类中的可见性,以及外部代码对基类接口的访问权限:
    • public继承:基类的public/protected成员在派生类中保留原有访问级别,外部代码可通过派生类对象访问基类public成员,且支持隐式类型转换。
    • private继承:基类的public/protected成员在派生类中变为private,外部代码无法访问基类任何成员,也不允许隐式转换为基类指针/引用,但派生类内部仍然可以访问基类的public/protected成员(比如第一个案例中D::foo()能调用A::foo())。
    • protected继承:基类的public/protected成员在派生类中变为protected,外部代码无法访问,但派生类的子类可以访问基类的protected成员。

内容的提问来源于stack exchange,提问作者Hardik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:53:31