本质上,我的问题是我正在使用的库中的函数(此代码中的函数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:数据存在于一个对象中,而另一个对象则在执行大多数数据操作。更加面向对象的方法是将操作和数据移到同一对象中。
显然,您提供给我们的示例代码比您的实际项目复杂得多,所以我不知道重组代码的最明智的方法。这里有一些建议:
class Bar
{
private:
Object* mbar;
public:
void FoobarFunction()
{
Foo(mbar);
}
};
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/