我们如何确定一个函数应该包含在哪个类中

时间:2013-07-22 21:33:17

标签: c++ oop

以停车场为例。设计一个停车场,在不同类型的停车位上管理停车/停放不同类型的汽车。我们可以先定义一个类ParkingLot,其中包含停车位,总楼层,宽度,停车场的长度等。然后我们定义类车辆,它可以由不同的车型继承,如汽车,Motercycle等。我们可以甚至定义类Parking_Slot类...

我感到困惑的是我应该在哪个类中实现park()和unpark()等动作函数。看来这些功能与我提到的所有三个类都有关:ParkingLot,Vehicle,Parking_Slot。

如果有多个相关的类,那么任何人都能解释一下我们应该在哪个类中放置一个函数吗?

5 个答案:

答案 0 :(得分:2)

查看single responsibility principle,它通常表示您应该为每个班级分配一组密切相关的操作。

尝试将您的班级分为名词和动词(动作),所以您可以说: -

  • 车辆 - > Park()
  • ParkingSlot - >接受(车辆)
  • ParkingLot - >管理(车辆),包含(汽车)

答案 1 :(得分:1)

这实际上取决于你想要实现的目标,不,这并不意味着“它无关紧要,我们可以把它放在任何一个班级中,只要它有效” - 通常有更多的方法即使好方法和坏方法全部“起作用”,也要设计出比设计得好的东西。显然,如果您不关心解决方案是否合适,可以做任何您喜欢的事情。

例如,如果您正在模拟一个试图通过决定哪些车辆去哪里来优化交通流量的停车场经理,那么显然您不希望单个车辆做出他们的停车决定,或者它会完全失去目的你正在努力实现的目标。也许你有一个经理对象将车辆对象放在停车场对象的停车位对象中,或者你可能简化并让停车场“做出决定”。如果你想模拟一个公共停车场被动发生的事情,那里的司机会选择他们来的第一个自由空间,那么也许你有车对象可以做到这一点。

与任何其他模型一样,您从现实中抽象出来,并专注于重要元素,因此您需要确定这些元素是什么,以及您希望它们做什么,并相应地设计您的类。一旦你找到适合你的特定应用程序的最佳模型,那么这些类几乎就会自己编写。

答案 2 :(得分:0)

如果我们将ParkingLot视为汽车的容器,那么通常情况下,park()函数应该在容器中。然而,根据您的设计如何发展,这种事情确实会发生变化。

答案 3 :(得分:0)

OOP是关于父子层次结构nad多态的,所以你可以在派生类中实现相同的函数。

例如,类ParkingLot.park()可能意味着搜索任何可用的停车位,而当您需要更准确地定义它时,您可以获得ParkingLot的孩子 - ParkingSlots并选择最适合您需求的停车位(例如停车场)禁用的插槽)。

ParkingLot.parkVehicleAnywhere(const Vehicle& vehicle);
Vehicle.park(const ParkingSlot& slot);
ParkingSlot.parkVehicle(const Vehicle& vehicle);

class Motorcycle : public Vehicle;
class Car : public Vehicle;

然后,您还可以使用 double dispatch 来确定2个所选组件之间交互的特定行为。

最后但并非最不重要的一点是,当你在派生中设置你的层次结构时,试着问问自己一个问题(例如)。

ParkingLot 车辆还是 车辆?

ParkingSlot 停车场或车辆?

摩托车车辆还是 车辆?

等等。问自己这些问题可以帮助你建立一个良好的对象层次结构。

答案 4 :(得分:0)

在C ++设计中,表达每个动作并不是强制性的 作为一种阶级的方法。

如果动作只修改了一个对象类型 你可以使动作成为该对象类的一种方法。如果是多个对象 类型X,Y [,Z ..]被修改然后更喜欢使动作a 自由功能:

foo(X &, Y &[, Z &...]);

即使只修改了一个对象类型T,您仍然应该更喜欢 如果你可以通过手段实现它,使操作成为一个自由函数 已经属于T的基本方法:

foo(T &, Y const &);

而不是:

T::foo(Y const &);

这将使T免于不必要的膨胀,并且还有更多 建议foo(t,y)不仅在t实际上是T时才有用 另外,“免费”,如果t属于可转换为T的类型,并且在{ 特别是从T派生的类型。