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
Why would the conversion between derived* to base* fails with private inheritance?
提问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'是主要的。
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)
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
Consider the 4th bullet- Once again this clause does not apply
考虑第二个要点-“R 出现在 N 类的成员或朋友中,...”。此条款不适用,因为“R”(主要)既不是“N”(派生)的成员也不是朋友
考虑第三个要点-“R 出现在 P 类的成员或朋友中......”。由于与上述相同的原因,本条款也不适用于
考虑第 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 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.
由于在 中访问时Base
不是可访问的类,因此从派生类到基类的标准转换是格式错误的。因此错误。Derived
main
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
, protected
and private
. Those are meant to determine WHO can access methods, attributes or base classes. It is typical amongst Object Oriented languages.
在 C++ 中,有 3 个访问级别说明符:public
,protected
和private
。这些旨在确定 WHO 可以访问方法、属性或基类。它在面向对象语言中很典型。
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.
在这里,你选择了private
继承。从概念上讲,这意味着您试图隐藏Derived
从Base
外部继承的事实,这通常意味着这是一个实现细节。
As a consequence, the "exterior" is unaware of this relationship. This is enforced by the compiler with this inaccessible
message.
结果,“外部”不知道这种关系。这是由编译器通过此inaccessible
消息强制执行的。
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.
从设计的角度来看,private
一般不需要继承。要么应用 Liskov 替换原则并且您使用public
继承,要么它是一个实现细节并且您使用组合。
回答by Windows programmer
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
.
您知道class derived
继承自class base
,但main()
函数不知道它。该main()
函数不知道的原因是您class derived
从class base
.
Therefore when you try to assign new derived
to 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() 函数声明为虚拟函数。虚函数可以用派生类代替。否则,您可能会收到编译器错误。