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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3674876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 13:27:40  来源:igfitidea点击:

Why would the conversion between derived* to base* fails with private inheritance?

c++privatebasederivedaccessible

提问by Bruce

Here is my code -

这是我的代码 -

#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;
}

This gives a compile time error.

这给出了编译时错误。

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

Since the compiler will try and call the base class sid()why do I get this error? Can someone please explain this.

既然编译器会尝试调用基类,sid()为什么会出现这个错误?有人可以解释一下。

采纳答案by Chubsdad

$11.2/4 states-

$11.2/4 州-

A base class B of N is accessible at R, if

  • an invented public member of B would be a public member of N, or
  • R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
  • R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private or protected member of P, or
  • there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R."

N 的基类 B 可在 R 处访问,如果

  • B 的发明公共成员将是 N 的公共成员,或
  • R 出现在类 N 的成员或朋友中,并且 B 的发明公共成员将是 N 的私有成员或受保护成员,或
  • R 出现在派生自 N 的类 P 的成员或朋友中,并且 B 的发明公共成员将是 P 的私有成员或受保护成员,或
  • 存在一个类 S 使得 B 是在 R 上可访问的 S 的基类,而 S 是在 R 上可访问的 N 的基类。”

Here 'B' is 'Base', 'N' is 'Derived' and 'R' is main.

这里'B'是'Base','N'是'Derived','R'是主要的。

  1. Consider the 2nd bullet- 'R occurs in a member or friend of a class N,...'. This clause does not apply as 'R'(main) is neither a member nor friend of 'N'(Derived)

  2. Consider the 3rd bullet- 'R occurs in a member or friend of a class P....'. This claus also does not apply for the same reasons as above

  3. Consider the 4th bullet- Once again this clause does not apply

  1. 考虑第二个要点-“R 出现在 N 类的成员或朋友中,...”。此条款不适用,因为“R”(主要)既不是“N”(派生)的成员也不是朋友

  2. 考虑第三个要点-“R 出现在 P 类的成员或朋友中......”。由于与上述相同的原因,本条款也不适用于

  3. 考虑第 4 点 - 该条款再次不适用

Thus we can conclude that 'Base' is not an accessible class of 'Derived'.

因此我们可以得出结论,'Base' 不是一个可访问的 'Derived' 类。

$11.2/5 states -

11.2 美元/5 个州 -

If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (4.10, 4.11). [ Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. —end note ]

如果基类是可访问的,则可以将指向派生类的指针隐式转换为指向该基类的指针 (4.10, 4.11)。[注意:因此类 X 的成员和朋友可以将 X* 隐式转换为指向 X 的私有或受保护的直接基类的指针。--尾注]

Since Baseis not an accessible class of Derivedwhen accessed in main, the Standard conversion from Derived class to Base class is ill-formed. Hence the error.

由于在 中访问时Base不是可访问的类,因此从派生类到基类的标准转换是格式错误的。因此错误。Derivedmain

EDIT 2:

编辑2:

Study the error messages of some popular compilers and that should help you get a better understanding. Note how the word 'inaccessible' pops up so frequently and consistently across all the error messages

研究一些流行编译器的错误消息,这应该有助于您更好地理解。请注意“无法访问”一词如何在所有错误消息中如此频繁且一致地弹出

The references are from the draft standard N3000. I am yet to download the latest draft :)

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

GCC prog.cpp: In function ‘int main()': prog.cpp:27: error: ‘base' is an inaccessible base of ‘derived'

Comeau Online "ComeauTest.c", line 26: error: conversion to inaccessible base class "base" is not allowed ptr = new derived;

VS2010 error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible

GCC prog.cpp:在函数“int main()”中:prog.cpp:27:错误:“base”是“派生”的不可访问基

Comeau Online“ComeauTest.c”,第 26 行:错误:不允许转换为无法访问的基类“base” ptr = new 派生;

VS2010 错误 C2243:“类型转换”:从“派生 *”到“基础 *”的转换存在,但无法访问

回答by Douglas Leeder

I suspect the problem is that you can't convert a derived pointer to a base pointer, as the inheritance is private.

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

回答by Matthieu M.

Chusbad provided an in-depth explanation involving the standard, I'll try to provide an accessible explanation.

Chusbad 提供了涉及标准的深入解释,我将尝试提供一个易于理解的解释。

In C++, there are 3 access level specifiers: public, protectedand private. Those are meant to determine WHO can access methods, attributes or base classes. It is typical amongst Object Oriented languages.

在 C++ 中,有 3 个访问级别说明符:public,protectedprivate。这些旨在确定 WHO 可以访问方法、属性或基类。它在面向对象语言中很典型。

Here, you elected privateinheritance. Conceptually this means that you seek to HIDE the fact that Derivedinherits from Baseto outsiders, which generally means this is an implementation details.

在这里,你选择了private继承。从概念上讲,这意味着您试图隐藏DerivedBase外部继承的事实,这通常意味着这是一个实现细节。

As a consequence, the "exterior" is unaware of this relationship. This is enforced by the compiler with this inaccessiblemessage.

结果,“外部”不知道这种关系。这是由编译器通过此inaccessible消息强制执行的。

From a design point of view, privateinheritance is not generally required. Either the Liskov Substitution Principle applies and you use publicinheritance, either it's an implementation detail and you use composition.

从设计的角度来看,private一般不需要继承。要么应用 Liskov 替换原则并且您使用public继承,要么它是一个实现细节并且您使用组合。

回答by Windows programmer

You know that class derivedinherits from class base, but the main()function doesn't know it. The reason the main()function doesn't know it is that you made class derivedinherit PRIVATELY from class base.

您知道class derived继承自class base,但main()函数不知道它。该main()函数不知道的原因是您class derivedclass base.

Therefore when you try to assign new derivedto ptr, the pointer types are not compatible.

因此,当您尝试分配new derived给 时ptr,指针类型不兼容。

回答by ereOn

Try this:

尝试这个:

#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;
}

回答by Santosh kumar

this gives error C2243: 'type cast' : conversion from 'derived *' to 'base *' exists, but is inaccessible This derived class has been inherited privately .so base class object is not gets created when derieved get creation happens. to create the derive object first calls goes to create the base class object that not happening. soltuion is to derive the class publicly. it doesnit matter whether your using virtual keyword with member functions or not.

这会产生错误 C2243:“类型转换”:从“派生 *”到“基 *”的转换存在,但无法访问此派生类已被私下继承。因此,在派生获取创建发生时,不会创建基类对象。创建派生对象首先调用去创建未发生的基类对象。解决方案是公开派生类。无论您是否使用带有成员函数的 virtual 关键字都没有关系。

回答by Alexander Rafferty

You need to declare your sid() function in the base class as virtual. A virtual function can be replaced by a derived class. Otherwise, you would likely get a compiler error.

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