我是一名 C++ 新手,但已经有多年使用面向对象语言如 C/C#/Objective-C 的经验。现在,我正在学习 C++。
我看到了这段 C++ 代码:
class World : public State
{
};
看起来类 World
公开继承了类 State
。
公开子类化?这很难理解。
这个特性的概念是什么? 以及何时使用或需要此功能?
我是一名 C++ 新手,但已经有多年使用面向对象语言如 C/C#/Objective-C 的经验。现在,我正在学习 C++。
我看到了这段 C++ 代码:
class World : public State
{
};
看起来类 World
公开继承了类 State
。
公开子类化?这很难理解。
这个特性的概念是什么? 以及何时使用或需要此功能?
在那里需要使用public
关键字的原因是,对于使用class
关键字定义的类,所有成员(数据成员、成员函数和基类)的默认访问修饰符都是private
。因此,
class World : State {};
与以下代码等效:
class World : private State {};
这可能不是您想要的 - 这意味着基类仅在World
类内部可访问。外部人员根本不知道存在继承关系。
对于使用关键字struct
定义的类,访问修饰符的默认值为public
,因此您可以编写以下代码:
struct World : State {};
想要得到一个既外表看起来,又行为类似于其他支持继承的语言的东西。但是struct
关键字及其定义类的事实,仅仅是为了与C兼容而存在。你不会在许多C++样式指南中找到推荐使用它的建议,只是为了获得默认的public可访问性 -普遍情况下只用于POD类或者可能仅用于没有成员函数的类。
至于为什么C ++首先有私有继承:对于大多数目的,私有继承是一种组合形式。普通的组合:
class World {
State state;
public:
void foo() {
state.bar();
state.baz();
and so on
}
};
也就是说,类World知道它是使用状态实现的,而外部世界不知道World是如何实现的。
与之相对。
class World : private State {
public:
void foo() {
bar();
baz();
and so on
}
};
换句话说,类“World”知道它是通过成为“State”实现的,并且外部世界不知道它是如何实现的。但是,您可以通过例如在World的公共部分中放置using State::bar;
来有选择性地暴露State接口的某些部分。效果就好像您费力地编写了一个函数(或多个重载),每个函数都将代理到State上的同一个函数。
除了避免输入之外,私有继承的另一个常见用途是当类“State”为空时,即没有数据成员时。然后,如果它是“World”的成员,则必须占用一些空间(尽管根据对象布局,这可能是否则将只是填充的空间,因此它不一定会增加“World”的大小),但如果它是基类,那么一个叫做“空基类优化”的东西就会发挥作用,它可以是零大小的。如果您要创建许多对象,则可能会很重要。私有继承启用了优化,但外部世界不会推断出“is-a”关系,因为它看不到继承。
这是一个相当微妙的区别——如果有疑问,只需使用显式组合即可。为了节省输入而引入继承是很好的,直到它有一些意外后果。
class World: private State
{
};
State
的public
和protected
成员将被World
继承并变为private
。这将State
封装在World
中。任何从World
继承的类都无法访问State
的任何特性。class Empty { };
class Foo
{
int foo;
Empty e;
};
class Bar : private Empty
{
int foo;
};
这里,sizeof(Foo)
可能是5,但是由于空的基类,sizeof(Bar)
将会是4。
World*
静态转换为State*
。 - Steve Jessopint
是4字节对齐的话,那么sizeof(Foo)
可能会是5或者更糟糕的8。 - Steve Jessop在祖先类名前的public/protected/private关键字表示从祖先继承的成员的可见性。使用private继承,子类只继承祖先的实现,而不继承接口。
class A {
public:
void foo();
};
class B : private A {
public:
void bar();
};
void B::bar()
{
foo(); // can access foo()
}
B b;
b.foo(); // forbidden
b.bar(); // allowed
class World: private State {}
?实际上你写的继承是公有的。 - Steve Jessopclass World: private State
? - detunized