为什么派生到基础*之间的转换会通过私有继承失败?
-
01-10-2019 - |
题
这是我的代码 -
#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()
为什么我会得到这个错误?有人可以解释一下。
解决方案
$ 11.2/4州 -
如果
- B的发明公共成员将是N或
- R发生在N类的成员或朋友中,B的发明公共成员将是N或受保护的成员
- R发生在n类P类的成员或朋友中,B的发明公共成员将是P的私人或受保护成员,或
- 存在S类,因此B是R和S可访问的S基类是可在R的N级的基类。”
这里的“ b”是“ base”,“ n”是“衍生”和“ r”是主要的。
考虑第二子弹 - r发生在n类的成员或朋友中,...'。本条款不适用,因为“ r”(main)既不是“ n”的成员,也不是朋友(派生)
考虑第三个子弹'r发生在P类的成员或朋友中。这个词也不适用于上述相同的原因
考虑第四个子弹 - 再次适用此条款
因此,我们可以得出结论,“基础”不是可访问的“衍生”类。
$ 11.2/5州 -
如果可以访问基类,则可以将指针隐式转换为派生类,以指向该基类的指针(4.10,4.11)。 [注意:X级的成员和朋友可以隐式将X*转换为X的私人或受保护的即时基类指针。— End Note
自从 Base
不是一个可访问的类 Derived
访问时 main
, ,从派生类转换为基类的标准转换是不形成的。因此错误。
编辑2:
研究一些流行编译器的错误消息,这应该有助于您获得更好的理解。请注意,“无法访问”一词如何如此频繁,一致地弹出所有错误消息
参考文献来自标准N3000草案。我尚未下载最新的草稿:)
gcc prog.cpp:在函数'int main()':prog.cpp:27:错误:'base'是“派生”的无法访问的基础
Comeau Online“ ComeAutest.c”,第26行:错误:不允许转换为不可访问的基类“基础”。
VS2010错误C2243:'类型cast':从“派生 *”转换为“基础 *”,但不访问
其他提示
我怀疑问题是您无法将派生指针转换为基本指针,因为继承是私人的。
Chusbad提供了涉及标准的深入解释,我将尝试提供一个可访问的解释。
在C ++中,有3个访问级别指定符: public
, protected
和 private
. 。这些旨在确定谁可以访问方法,属性或基类。它在面向对象的语言中是典型的。
Here, you elected private
遗产。从概念上讲,这意味着您试图掩盖一个事实 Derived
继承 Base
对于局外人来说,这通常意味着这是一个实施细节。
结果,“外部”没有意识到这种关系。这是由编译器强制执行的 inaccessible
信息。
从设计的角度来看, private
通常不需要继承。 Liskov替代原则要么适用,您可以使用 public
继承,要么是实现细节,因此您使用构图。
你知道的 class derived
继承 class base
, ,但是 main()
功能不知道。原因 main()
功能不知道是您制作的 class derived
私下继承 class base
.
因此,当您尝试分配 new derived
到 ptr
, ,指针类型不兼容。
试试这个:
#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;
}
这给出了错误C2243:“类型cast':从“派生 *”到“ base *”的转换,但是无法访问该派生类已被私下继承。为了创建派生对象,首先调用将创建不发生的基类对象。 Soltuion是公开得出班级。无论您是否使用虚拟关键字与成员函数使用,这都不重要。
您需要在基类中声明您的SID()函数为虚拟。虚拟功能可以用派生类代替。否则,您可能会遇到编译器错误。