代码之家  ›  专栏  ›  技术社区  ›  Bruce

为什么派生*到基*之间的转换会因私有继承而失败?

  •  20
  • Bruce  · 技术社区  · 15 年前

    这是我的密码-

    #include<iostream>
    using namespace std;
    
    class base
    {
    public:
        void sid()
        {
        }  
    };
    
    class derived : private base
    {
    public:
        void sid()
        {
        }
    };
    
    int main()
    {
        base * ptr;
        ptr = new derived; // error: 'base' is an inaccessible base of 'derived'
        ptr->sid();
        return 0;
    }
    

    这会产生编译时错误。

    error: 'base' is an inaccessible base of 'derived'
    

    因为编译器将尝试调用基类 sid() 为什么会出现此错误?有人能解释一下吗?

    7 回复  |  直到 9 年前
        1
  •  16
  •   RBerteig Keith Adler    15 年前

    $1.2/4状态

    如果

    • B的发明公共成员将是N的公共成员,或者
    • r出现在n类的成员或朋友中,以及被发明的公众中。 B的成员将是私人或 n的受保护成员,或
    • r出现在从n派生的类p的成员或友元中,并且 发明了B的公共成员将是A P的私人或受保护成员,或
    • 存在一个类S,使得B是在R处可访问的S的基类 s是n个可访问的基类 在R”

    这里“b”是“base”,“n”是“derived”,“r”是“main”。

    1. 考虑第二个项目符号-“r发生在n类的成员或朋友中,…”。此子句不适用,因为“r”(main)既不是“n”(派生)的成员也不是“n”的朋友。

    2. 考虑第3个项目符号-“R出现在类P的成员或朋友中…”。本条款也不适用于上述原因。

    3. 考虑第4个项目符号-再次说明,本条款不适用

    因此,我们可以得出结论,“base”不是“derived”的可访问类。

    $11.2/5州-

    如果基类是 可访问,可以隐式转换 指向派生类的指针 指向该基类的指针(4.10, 4.11)。[注:X班的成员和朋友可以 将x*隐式转换为指针 私人或受保护的立即 X.尾注的基本分类]

    自从 Base 不是的可访问类 Derived 当进入时 main 从派生类到基类的标准转换格式错误。因此出现了错误。

    编辑2:

    研究一些流行的编译器的错误消息,这将帮助您更好地理解。注意“不可访问”这个词是如何在所有错误消息中如此频繁和一致地弹出的。

    参考文件来自标准草案N3000。我还没有下载最新的草稿:)

    gcc prog.cpp:在函数__int中 main()_:prog.cpp:27:错误:__base_ _派生_

    comeau在线“comeautest.c”,第26行: 错误:转换到不可访问的基 “基础”类不是 允许 ptr=新派生的;

    VS2010错误C2243:“类型转换”: 从“derived*”转换为“base” *'存在,但无法访问

        2
  •  35
  •   Douglas Leeder    15 年前

    我怀疑问题在于不能将派生指针转换为基指针,因为继承是私有的。

        3
  •  8
  •   Matthieu M.    15 年前

    丘斯巴德提供了一个涉及该标准的深入解释,我将尽力提供一个易于理解的解释。

    在C++中,有3个访问级别说明符: public , protected private . 它们是用来确定谁可以访问方法、属性或基类的。它在面向对象语言中是典型的。

    在这里,你选了 私有的 继承。从概念上讲,这意味着你试图隐藏这样一个事实: Derived 继承自 Base 对于外部人员,这通常意味着这是一个实现细节。

    因此,“外部”并不知道这种关系。这是由编译器用这个 inaccessible 消息。

    从设计的角度来看, 私有的 通常不需要继承。无论是应用Liskov替换原则还是使用 公众的 继承,或者它是一个实现细节,您可以使用组合。

        4
  •  6
  •   RBerteig Keith Adler    15 年前

    你知道 class derived 继承自 class base 但是 main() 函数不知道。原因 主体() 功能不知道是你做的 类派生 私人继承自 阶级基础 .

    因此,当你试图分配 new derived ptr ,指针类型不兼容。

        5
  •  5
  •   ereOn    15 年前

    试试这个:

    #include<iostream>
    #include<conio.h>
    using namespace std;
    
    class base
    {
          private:
          public:
              virtual void sid() // You might want to declare sid virtual
                 {
                      cout<<"base";
                 } 
              virtual ~base() // You then probably need a virtual destructor as well.
                 {
                 } 
    };
    
    class derived : public base //public inheritance
    {
          private:
          public:
                 void sid()
                 {
                      cout<<"derived";
                 }
    };
    
    int main()
    {
        base * ptr;
        ptr = new derived;
        ptr->sid();
        getch();
        return 0;
    }
    
        6
  •  1
  •   Santosh kumar    15 年前

    这将产生错误C2243:“类型转换”:存在从“derived*”到“base*”的转换,但无法访问 此派生类已被私有继承,因此在Derieved get创建时不会创建基类对象。要创建派生对象,首先调用创建未发生的基类对象。 解决方法是公开派生类。无论您是否将虚拟关键字与成员函数一起使用,这都无关紧要。

        7
  •  0
  •   Alexander Rafferty    15 年前

    您需要将基类中的sid()函数声明为虚函数。可以用派生类替换虚拟函数。否则,您可能会得到一个编译器错误。