一个班级应该直接使用其私人会员还是其公开的会员职能?

时间:2010-02-19 00:19:41

标签: language-agnostic encapsulation

嗯,我不确定这个。

我有一个像

这样的课程
    class Object
    {
        int internalValue ;
        struct SomeStructType
        {
            int superInternalValue ;
        } someStruct ;

    public:
        int getInternalValue()
        {
            return internalValue ;
        }

        int getSuperInternalValue()
        {
            return someStruct.superInternalValue ;
        }

        void printThatInternalValue()
        {
            // Its seems pretty clear we should just access
            // the private value directly and not use the public getter
            printf( "%d", internalValue ) ;
        }

        void printThatSuperInternalValue()
        {
            // Now here the access pattern is getting more complicated.
            // Shouldn't we just call the public access function
            // getSuperInternalValue() instead, even though we are inside the class?
            printf( "%d", someStruct.superInternalValue ) ;
        }
    } ;

因此对于类的INTERNAL操作,它可以直接使用someStruct.superInternalValue,但使用类的公共getter函数getSuperInternalValue()似乎更简洁。

我能看到的唯一缺点是,如果您尝试使用getter修改superInternalValue会给您一份副本,在这种情况下显然不是您想要的。但是对于读取访问,是否应该在类内部使用公共getter函数?

5 个答案:

答案 0 :(得分:3)

如果无法覆盖访问者,则类可以直接使用其私有成员。否则,它应该使用访问器,这样如果它被覆盖,该类将继续正常运行。

答案 1 :(得分:1)

我可以看到使用公共访问器的唯一另一个原因是,如果访问者执行其他操作,然后只返回保存在变量中的值;例如,如果内存中的变量由于某种原因无效,则返回默认值。

在您给出的示例中,无论哪种方式都可以,并且直接访问变量意味着程序可以使用更少的代码来获取要显示的值。

答案 2 :(得分:1)

我会说至少有90%的时间会出现这样的问题,这是一个很好的迹象,表明你可能试图将过多的功能放入一个类中。如果someStruct::SuperInternalValue真的应该通过getSuperInternalValue访问,那么很有可能它应该成为someStruct的一部分,而不是Object的一部分。

同样,如果您需要打印出someStruct,那么Object应该只使用成员函数(或使用支持它的语言重载运算符)来打印出someStruct对象(作为整个)。正如您所写的那样,Object::printThatSuperInternalValue知道关于someStructsuperInternalValue的所有

尽管源代码包含“class”和“Object”,但您真正拥有的代码是Object中代码someStruct中的哑数据。换句话说,你拥有的东西根本就不是OO - 它是带有数据结构的简单程序代码。这不一定都是坏的,但基于encapsulation标签,我认为这可能不是你真正想要的。

class Object { 
    int internalValue;
public:
    class someStruct { 
        int superInternalValue;
    public:
        someStruct(int v) : superInternalValue(v) {}
        someStruct &operator=(someStruct const &n) { 
             superInternalValue = n.superInternalValue;
             return *this; 
        }
        friend ostream &operator<<(ostream &os, someStruct const &s) {
            return os << s.superInternalValue;
        }
    };
    friend ostream &operator<<(ostream &os, Object const &o) { 
        return os << internalValue;
    }
};

这样我们就界面定义someStruct(我们可以从int创建一个,分配它们并打印它们)而Object不需要处理/ touch superInternalValue一点都不重要的部分并不是我们已经停止 Objectsomestruct的内部结合,但我们已经someStruct足够聪明Object {1}}现在可以忽略someStruct实施方式的所有细节。

答案 3 :(得分:0)

我建议,如果有疑问,请使用访问者。

虽然访问器最初可以作为一个简单的包装器,只能获取私有成员的价值,但是对访问者的未来修改可能会改变这种行为,使得任何其他直接访问该成员的方法不再具有对其价值的一致看法。

答案 4 :(得分:0)

一切都取决于。我不认为一般来说你应该在课堂上使用getter。例如,

int MyClass::getFoo() const
{
   int retval(0);
   m_myMutex.lock();
   retval = m_foo;
   m_myMutex.unlock();
   return retval;
}

你可能不会在MyClass中使用这样的getter。