C ++子类访问修饰符?
Posted
技术标签:
【中文标题】C ++子类访问修饰符?【英文标题】:C++ subclassing access modifier? 【发布时间】:2011-06-13 16:49:59 【问题描述】:我是 C++ 新手,对 C/C#/Objective-C 等 OO 语言有多年经验。现在,我正在学习 C++。
我看到了这个 C++ 代码:
class World : public State
;
似乎World
类公开继承了State
类。
公共子类化?很难理解。
这个功能的概念是什么? 这在什么时候有用或需要?
【问题讨论】:
您的意思是写class World: private State
吗?在您实际编写的内容中,继承是公开的。
你的意思是class World: private State
?
@Steve, @detunized 我很抱歉我犯了愚蠢的错误。我修改了问题。
public
继承是“正常”继承,例如在 C# 中(仅命名您知道的一种语言),问题出在哪里?我发现更难理解private
继承。
@Eonil:嗯,好吧。 :) 顺便说一下,你可以省略继承访问修饰符,但是对于类,它默认为private
,这在 99% 的情况下是无用的(对于structs
,默认为public
).
【参考方案1】:
public
关键字的需要只是对于使用关键字class
定义的类,默认访问修饰符(对于所有内容 - 数据成员、成员函数和基类)是 private
。所以
class World : State ;
等同于:
class World : private State ;
这可能不是您想要的 - 这意味着基类只能在类 World
中访问。外人“根本不知道”遗产的存在。
对于使用关键字struct
定义的类,默认的访问修饰符是public
,所以你可以写:
struct World : State ;
并获得一些外观和行为都与其他所有具有继承的语言相似的东西。但是struct
关键字,以及它定义了一个类的事实,实际上只是为了与 C 兼容。你不会发现很多 C++ 风格指南推荐使用它只是为了获得默认的公共可访问性——通常是仅用于 POD 类,或者可能仅用于根本没有成员函数的类。
至于为什么 C++ 首先具有私有继承:对于大多数用途而言,私有继承是一种组合形式。正常构图:
class World
State state;
public:
void foo()
state.bar();
state.baz();
and so on
;
也就是说,World 类知道它是使用 State 实现的,而外界不知道 World 是如何实现的。
对比
class World : private State
public:
void foo()
bar();
baz();
and so on
;
也就是说,World 类知道它是通过作为一个 State 来实现的,而外界不知道它是如何实现的。但是您可以选择性地公开部分状态接口,例如将using State::bar;
放在 World 定义的公共部分中。效果就像您在 World 中费力地编写了一个函数(或多个重载),每个函数都委托给 State 上的相同函数。
除了避免打字之外,私有继承的一个常见用途是当类State
为空时,即没有数据成员。然后,如果它是World
的成员,它必须占用一些空间(诚然,根据对象布局,这可能是空间,否则只是填充,所以它不一定会增加World
的大小),但如果它是一个基类,然后一个称为“空基类优化”的东西开始起作用,它可以是零大小。如果您要创建 很多 个对象,这可能很重要。私有继承启用优化,但外部世界不会推断“is-a”关系,因为它看不到继承。
这是一个非常好的区别 - 如果有疑问,只需使用显式组合即可。引入继承来节省类型非常好,直到它产生一些意想不到的后果。
【讨论】:
谢谢。接受,因为最后一段:)【参考方案2】:万一
class World: private State
;
私有继承意味着State
的所有public
和protected
成员都将被World
继承并变为private
。这将State
密封在World
内。从World
继承的任何类都不能访问State
的任何功能。
【讨论】:
【参考方案3】:是什么让您认为它是私人的?它在那里说 public ,这意味着它是公开的子类化。
除此之外,私有继承和受保护继承的作用与公共继承相同,只是所有成员变量都是函数,至少具有私有或受保护的可访问性。例如,如果State
有一个公共成员函数 'foo()',它在 'World' 中将是私有的。
这在实践中很少使用,但它确实有目的。我见过的最常见的用法是通过继承进行组合。即,您想要“具有”关系而不是“是”(通常通过公共继承获得)。通过私有继承类,您可以获得它的所有变量和方法,但不会将它们暴露给外界。
使用私有继承进行组合的一个优势来自空基类优化 (EBCO)。使用普通组合,拥有一个空类的成员对象仍将使用至少 1 个字节,因为所有变量都必须具有唯一的地址。如果您私下继承您想要组成的对象,那么这不适用并且您不会遭受内存损失。
例如
class Empty ;
class Foo
int foo;
Empty e;
;
class Bar : private Empty
int foo;
;
这里,sizeof(Foo)
可能是 5,但 sizeof(Bar)
将是 4,因为基类为空。
【讨论】:
“与公共继承相同,除了...”。区别不止于此。此外,例如,外人不能将World*
静态转换为 State*
。
"sizeof(Foo) 可能是 5" - 或者更糟糕的是 8,如果 int
在您的实现中是 4 对齐的。【参考方案4】:
祖先类名称前的 public/protected/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
一般来说,您应该使用公共继承,因为继承不应仅用于实现重用(私有继承就是这样做的)。
【讨论】:
以上是关于C ++子类访问修饰符?的主要内容,如果未能解决你的问题,请参考以下文章