【发布时间】:2009-11-19 02:54:39
【问题描述】:
如果我正在创建一个抽象基类,并且从它派生的类将具有一些相同的数据成员,最好将这些成员设为抽象基类中的私有成员并为它们提供受保护的访问权限?或者不打扰,只是将数据成员放在派生类中。这是用 C++ 编写的。
【问题讨论】:
标签: c++
如果我正在创建一个抽象基类,并且从它派生的类将具有一些相同的数据成员,最好将这些成员设为抽象基类中的私有成员并为它们提供受保护的访问权限?或者不打扰,只是将数据成员放在派生类中。这是用 C++ 编写的。
【问题讨论】:
标签: c++
在 OOP 设置中要问的主要问题是:这些数据属于哪里?
在继承关系中,数据(和功能)应在其或多或少不变的最高阶段定义。这促进了最大的模块化和代码重用。例如,假设有两个类:
class Human;
class Student : public Human;
在添加数据成员“m_Arms”时,我们根据以下问题确定“人类”级别是定义数据、其用途及其对派生类的可见性的最佳位置:
应该从基类的角度考虑上下文——即使有一个额外的 is-a-Human 类可以做一些额外的事情,那么它也需要访问数据。例如如果出于某种原因,您选择 Robocop 类:public Human,您需要直接访问他的大腿才能将枪存放在里面。在这种架构下,Thigh 需要对 Human 的所有子类可见。
可以使用相同的数据模块化、功能模块化和可见性原则来优化架构。例如,在定义 Robocop 类时,可以将基类 Human 进一步提取,如下所示,以允许更改可见性,并随之更改功能。
class Human;
class NormalHuman : public Human; //declare Thigh private here.
class SuperHuman : public Human; //continue using Thigh as protected.
此外,Arms 本身可能是多态的,允许(请原谅意外的反乌托邦解释)基于工厂的架构使用人类部件模块化组装不同类型的人类。
【讨论】:
如果数据属于派生类,让派生类做它想要包含该数据的事情。
通过将这些数据放在基类中(不是私有的),你强制每个派生类都拥有它。例如,不应强制派生类做任何事情除非他们需要填写数据成员。基类定义派生类必须做什么,而不是它们应该如何做。
如果您发现可能有一个共同的主题,您可以创建一个包含这些成员和实现的派生类,然后将其作为那些想要使用它的人的基类。例如:
struct car
{
virtual ~car(){}
virtual unsigned year(void) const = 0;
virtual const std::string make(void) const = 0;
}
// Dodge cars can feel free to derive from this instead, it's just a helper
struct dodge_car
{
virtual ~car(){}
virtual unsigned year(void) const = 0;
const std::string make(void) const
{
static const std::string result = "Dodge";
return result;
}
}
等等。但是你看,任何派生类仍然可以选择实现整个汽车接口。这也提高了代码的清洁度。通过保持你的接口是一个真正的接口,实现细节不会成为阻碍。
您的基类使用的任何变量都应该是私有的,因为派生类不需要知道它是如何工作的,就像派生类的用户不需要知道派生类的内部是如何工作的一样。
【讨论】:
如何将成员设为私有并提供受保护的访问权限?
派生类不能访问基类的私有成员。 派生类 A 和派生类 B 都需要您所说的那些数据成员吗?如果是,则将它们放入基类并使其受保护。
我知道,我实际上想发表评论,但我不知道如何发表评论。我可能需要更多的声望吗?
【讨论】:
在编写基类时,不要考虑您的某些派生类会做什么,而要考虑所有它们必须做什么。换句话说,想想基类本身和它做出的保证——它的接口。
C++ 没有单独的“接口定义”概念,只是为此重用类。 (或避免在模板中输入。)因此,请注意编写抽象接口类的方式,以免对实现施加限制。
我没有回答“是”或“否”,因为您没有提供足够的信息,答案取决于其他细节;但如果你遵循我简要列出的指导方针,你的状态就会很好。
【讨论】:
在基类中包含一些数据(以及实现,即方法)并没有错。
基类可以是虚拟的,因为只有一个方法必须在派生类中实现。将这些[基类的]变量和方法设为私有、受保护甚至是公共的,取决于具体情况。
例如,基类可以有一个公共方法、一个受保护的方法和/或数据,以及一些私有方法。
【讨论】: