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

发布于 2024-09-19 04:03:17 字数 511 浏览 17 评论 0原文

这是我的代码 -

#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() 为什么我会收到此错误?有人可以解释一下吗?

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

他不在意 2024-09-26 04:03:17

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

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

笨笨の傻瓜 2024-09-26 04:03:17

$11.2/4 州-

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

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

这里 'B' 是 'Base','N' 是 'Derived','R' 是 main。

  1. 考虑第二个项目符号 - 'R 出现在 N 类的成员或朋友中,.. .'。本子句不适用,因为 'R'(主)既不是 'N'(派生)的成员也不是友元

  2. 考虑第三个项目符号 -“R 出现在 P 类的成员或友元中” ....'。出于与上述相同的原因,该条款也不适用

  3. 考虑第四个项目符号-再次此条款不适用

因此我们可以得出结论“Base”不是可访问的“派生”类别

$11.2/5 表示 -

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

由于在 main 中访问时 Base 不是 Derived 的可访问类,因此从 Derived 类进行标准转换到基类的格式不正确。因此出现了错误。

编辑 2:

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

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

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

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

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

$11.2/4 states-

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."

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

  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

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

$11.2/5 states -

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 ]

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

EDIT 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 :)

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

柒七 2024-09-26 04:03:17

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

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

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

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

从设计的角度来看,通常不需要私有继承。要么应用里氏替换原则并使用公共继承,要么它是实现细节并使用组合。

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

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

Here, you elected private inheritance. Conceptually this means that you seek to HIDE the fact that Derived inherits from Base to outsiders, which generally means this is an implementation details.

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

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

如果没有你 2024-09-26 04:03:17

您知道派生类继承自类基,但main()函数不知道这一点。 main() 函数不知道的原因是您使派生类基类私有继承。

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

You know that class derived inherits 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 derived inherit PRIVATELY from class base.

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

甜柠檬 2024-09-26 04:03:17

试试这个:

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

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;
}
川水往事 2024-09-26 04:03:17

这给出了错误 C2243:“类型转换”:从“派生 *”到“基 *”的转换存在,但无法访问
该派生类已被私有继承。因此,当派生类创建时,不会创建基类对象。要创建派生对象,首先调用创建未发生的基类对象。
解决方案是公开派生该类。是否在成员函数中使用 virtual 关键字并不重要。

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.

小…红帽 2024-09-26 04:03:17

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文