c++ - 将函数调用转发给成员是不好的做法吗?

标签 c++ oop

在我最近写的代码中,我不得不直接访问一个对象的成员来调用它的函数,但是,这样做感觉不对,因为它似乎违反了封装和迪米特法则。然而,我能想到的唯一好的选择是在类中为我可能想调用的那个成员的每个函数编写我自己的函数,这将非常乏味和多余。示例:

class Object
{
    public:
        void setNum(int x)
        {
            num = x;
        }

    private:
        int num;
};

class Object2
{
    public:
        Object obj;
};

int main()
{
    Object2 obj2;
    obj2.obj.setNum(5);
}

对比

class Object
{
    public:
        void setNum(int x)
        {
            num = x;
        }

    private:
        int num;
};

class Object2
{
    public:
        void setNum(int x)
        {
            obj.setNum(x);
        }

    private:
        Object obj;
};

int main()
{
    Object2 obj2;
    obj2.setNum(5);
}

Object2 中对 setNum 的调用被转发到 Object 中的相同函数。这样的设计被认为是不好的做法吗?直接访问 obj 会更好吗?

我也可以让 Object2 继承自 Object,但在这种情况下,我要继承的类不是设计为基类,会公开 protected 成员到 Object2,并且似乎不适合作为开始,因为它不是 is-a 关系,并且组合是首选。

我的具体情况:我正在使用 SFML 制作游戏,有一个 Ship 类当然需要一个 sprite 来表示它在世界中。任何时候我想设置或获取船的位置、旋转等。我要么直接访问它的 Sprite ,要么在 Ship 中编写一个冗余的转发函数。问题在于,做其中任何一件事情都像是一种代码味道:要么违反封装和 Demeter 法则,要么编写冗余代码。

这里什么是最佳实践?我是否对编写简单的转发功能过于挑剔?或者在这种情况下直接访问 Ship 的 Sprite 真的没有错吗?

本题:C++ Forward method calls to embed object without inheritance事实上,这正是我要问的,但是,这两个答案都没有提供好的解决方案。一个没有得到宽恕,显然封装很差,另一个只是使用 setter/getter ,如果有的话,这似乎是安慰剂,没有人解决我的主要问题,什么是最优雅和可接受的解决方案?

最佳答案

哪种解决方案最好在很大程度上取决于封装的底层语义。您需要尽可能地解耦代码。我将在示例中对此进行描述:

  1. 您有一个 Ship 类,它有一个 Sprite。您可能希望将游戏逻辑和渲染分开。所以 Ships 对渲染的了解就是它有一个处理它的 Sprite 对象。所以在这种情况下,您正在分离职责,这很好。所以简单的 getter 是一个很好的解决方案。
  2. 但是如果绝对坐标和旋转必须存储在 Sprite 中,那么事情就变了:游戏逻辑通常需要它们两个,所以它们必须在船舶和 Sprite 中设置一致。实现这一目标的最佳方法是让 Ship 的 setPosition 和 setRotation 方法也设置 Sprites 的位置和旋转。通过这种方式,您可以简化与 Ship 一起工作的代码,但会降低 Ship 的复杂性。鉴于 Ship 是从多个地方操纵的,这是值得的。注意:您仍然可能希望通过 getter 公开 Sprite 以进行渲染。你可能想阻止除 Ship 之外的任何人设置 Sprite 位置和旋转,如果这不会使你的代码膨胀太多的话。
  3. 让我们假设 Ship 类主要用于渲染。在这种情况下,您可能希望对使用 sprite 进行图形处理的外部类隐藏(因为如果您更改渲染引擎,那么除了渲染代码之外不需要重写任何东西将会很好)。在这种情况下,您将希望通过 Ship 将所有 setPosition 和 setRotation 调用代理到 ​​Sprite,以隐藏 Sprite 的存在。

在这些情况下都没有使用继承,因为继承意味着 child 是其祖先的变体。您可以说 BattleShip 是 Ship 的变体。但是 Ship 不是 Sprite 的变体,它们太不同了,意味着不同的东西。

所以:如果封装的类过于具体,不应该在外面可见,或者必须和一个master对象一致操作,那么写一堆代理方法是一个很好的解决方案。否则这些方法只会使您的代码膨胀,最好提供一种获取嵌套对象的方法。但在那种情况下,我投票支持 getter 方法而不是公共(public)属性。

关于c++ - 将函数调用转发给成员是不好的做法吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39689944/

相关文章:

c++ - c2447错误学习创建Win32窗口

C++ (g++) 编译错误,预期为 "="/etc。 'MyWindow"(我的类(class)名称)之前

c++ - 如何将 C++ 库作为共享对象文件 (.so) 加载到 Python 中?

java - 如何创建启动 Activity 的方法?

Java:OOP,多重扩展

c++ - 从多项式函数字符串动态分配数组

c++ - 在C++中使用变量而不是 `#define`指定数组大小是否不好? (C错误: variably modified at file scope) [closed]

Javascript 用 props 扩展类?

javascript - 如何停止间隔?

javascript - 面向对象的javascript : initialize an attribute with a self function call