Должен ли класс использовать свои закрытые члены напрямую или открытые функции-члены? - PullRequest
3 голосов
/ 19 февраля 2010

Ну, я не уверен насчет этого.

У меня есть класс, как

    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 ) ;
        }
    } ;

Так что для ВНУТРЕННИХ операций класса он МОЖЕТ использовать someStruct.superInternalValue напрямую, но кажется более понятным использовать вместо него публичную функцию получения класса getSuperInternalValue().

Единственный недостаток, который я вижу, это то, что если вы попытаетесь изменить superInternalValue, используя геттер, вы получите копию, что явно не то, что вам нужно в этом случае. Но для доступа к чтению, должна ли публичная функция получения использоваться внутри класса?

Ответы [ 5 ]

3 голосов
/ 19 февраля 2010

Если метод доступа не может быть переопределен, класс может напрямую использовать свои закрытые члены. В противном случае ему следует использовать метод доступа, поэтому если он будет переопределен, класс продолжит работать правильно.

1 голос
/ 19 февраля 2010

Я бы сказал, по крайней мере, в 90% случаев, когда возникают подобные вопросы, это хороший признак того, что вы, вероятно, пытаетесь использовать слишком много функциональности в одном классе. Если к someStruct::SuperInternalValue действительно нужно получить доступ через getSuperInternalValue, то вполне вероятно, что он должен быть частью someStruct, а не частью Object.

Аналогично, если вам нужно распечатать someStruct, тогда Object должен просто использовать функцию-член (или перегруженный оператор на языке, который его поддерживает), чтобы распечатать объект someStruct (в целом). Как вы уже написали, Object::printThatSuperInternalValue знает все о someStruct и superInternalValue.

Несмотря на исходный код, содержащий «класс» и «объект», у вас действительно есть код в Object, действующий на немых данных в someStruct. Другими словами, то, что у вас есть, на самом деле вовсе не ОО - это простой процедурный код со структурой данных. Это не обязательно все плохо, но, основываясь на теге 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. Важно не то, что мы остановили Object от игры с внутренностями somestruct, но мы сделали someStruct достаточно умным, чтобы Object теперь мог игнорировать все кровавые подробности того, как someStruct реализовано.

1 голос
/ 19 февраля 2010

Единственная другая причина, по которой я вижу использование общедоступного метода доступа, заключается в том, что метод доступа делает что-то другое, а не просто возвращает значение, сохраненное в переменной; например, возвращая значение по умолчанию, если переменная в памяти по какой-то причине недопустима.

В приведенном вами примере все в порядке, а прямой доступ к переменной означает меньше кода для вашей программы, чтобы получить значение для отображения.

0 голосов
/ 19 февраля 2010

Все зависит. Я не думаю, что в целом вы должны использовать геттер внутри класса. Например,

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

Вероятно, вы не будете использовать такой метод получения в MyClass.

0 голосов
/ 19 февраля 2010

Я бы предложил, если есть сомнения, использовать аксессор.

Хотя метод доступа может изначально действовать как простая оболочка, которая не делает ничего, кроме получения значения закрытого члена, будущая модификация метода доступа может изменить это поведение так, что любой другой метод, обращающийся к члену напрямую, больше не последовательное представление о его стоимости.

...