本质上,我的问题是我正在使用的库中的函数(此代码中的函数Foo)需要指向对象(Object * mbar)的指针作为参数。但是,mbar是bar的私有(private)成员变量。

通常,我只使用getter并按值传递,但是如果传递指针,则将直接访问资源,这将破坏封装。任何代码都可以调用getter并获得自由修改的权限。

我想到的第二件事是我可以使用const指针,因为它们不允许修改指向的资源,但是据我所知,我需要修改Foo来接受它,这是不可能的,因为它是一个库函数。

我能想到的最后一件事就是简单地使用Bar的 friend 调用FoobarFunction,但是一直有人告诉我, friend 函数是不得已的方法。

有没有办法在不破坏封装的情况下做到这一点?

//Main.cpp

#include "Foobar.h"

int main()
{
    Foobar fb;
    Bar b;
    fb.FoobarFunction(b);
    return 0;
}

//Bar.h

#include "Object.h"

class Bar
{
private:
    Object* mbar;
};

//Foobar.h

#include "Foo.h"
#include "Bar.h"

class Foobar
{
public:
    void FoobarFunction(Bar bar)
    {
        Foo(bar.mbar);
    }
};

最佳答案

简便的出路

您可以将指针设为const,然后在将其传递给库函数时进行强制转换

Foo(const_cast<Object *>(bar.mbar));

如果Foo不尝试修改mbar,这将起作用。强制转换“仅以名称”删除常量。尝试修改 secret 常量值可能会导致“可怕的事情”。

但是真的

即使有一种使Bar返回“只读”指针的方法,问题中的代码示例仍然会违反封装。这种非封装的特殊方式称为feature envy:数据存在于一个对象中,而另一个对象则在执行大多数数据操作。更加面向对象的方法是将操作和数据移到同一对象中。

显然,您提供给我们的示例代码比您的实际项目复杂得多,所以我不知道重组代码的最明智的方法。这里有一些建议:
  • 将FoobarFunction移至Bar:
    class Bar
    {
    private:
        Object* mbar;
    public:
        void FoobarFunction()
        {
            Foo(mbar);
        }
    };
    
  • 使用dependency injection。在创建Bar之前初始化mbar,然后将mbar传递给Bar的构造函数。
    int main()
    {
        Object *mbar;
        Foobar fb;
        Bar b(mbar);
        fb.FoobarFunction(mbar);
        return 0;
    }
    

    在此示例中,Bar不再是mbar的“所有者”。 main方法直接创建mbar,然后将其传递给需要它的任何人。

    乍一看,此示例似乎违反了我之前提到的准则(数据和行为存储在不同的对象中)。但是,上述内容与在Bar上创建 setter/getter 之间存在很大差异。如果Bar具有getMBar()方法,那么世界上任何人都可以出现并捕获mbar并将其用于他们想要的任何邪恶目的。但是在上面的示例中,mbar(主)的所有者完全控制了何时将其数据提供给另一个对象/功能。

  • 除C++外,大多数面向对象的语言都没有“friend”构造。根据我自己的经验,依赖注入(inject)是解决许多 friend 设计要解决的问题的更好方法。

    关于c++ - 当变量恰好是指针时,如何在非成员函数中使用私有(private)成员变量?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23320487/

    10-10 16:29