Когда функции должны быть функциями-членами?

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

Например, если есть некоторый класс A, он напишет глобальные функции типа:

void foo( A *ptrToA ){}

или же:

void bar( const A &refToA ){}

Мой первый инстинкт при взгляде на такие глобальные функции: «Почему не эти члены A?» Он будет настаивать на том, что это согласуется с рекомендациями для хорошей практики в C ++, потому что foo и bar могут выполнять все, что им нужно, используя открытый интерфейс A. Например, он будет утверждать, что это полностью соответствует с Скоттом Мейерсом Эффективные рекомендации C ++. Мне трудно согласовать это с пунктом 19 в этой книге, в котором в основном говорится, что все должно быть функцией-членом с несколькими исключениями (operator << и operator >> и функции, которые требуют динамического преобразования типов). Кроме того, хотя я согласен с тем, что функции могут делать то, что им нужно, с общедоступным интерфейсом A, по моему мнению, это во многом является результатом того, что люди пишут классы, которые имеют методы получения и установки для каждого члена данных класса А. открытый интерфейс, A - это чрезмерно прославленная структура, и вы, безусловно, можете делать с открытым интерфейсом все, что угодно. Лично я не думаю, что это следует использовать, я думаю, что это не следует поощрять.

Очевидно, что это возможно только в языке, подобном C ++, который не является чисто объектно-ориентированным, поэтому я предполагаю, что один из способов взглянуть на это состоит в том, что мой коллега не одобряет чисто объектно-ориентированный подход к разработке программного обеспечения. Кто-нибудь знает какую-либо литературу, которая поддерживает эту позицию как лучшую практику? Или кто-то согласен с этим и может объяснить это мне иначе, чем мой коллега, чтобы я мог увидеть свет? Или все согласны с моим нынешним ощущением, что это не имеет особого смысла?

Редактировать: Позвольте мне привести лучший пример кода.

class Car
{
    Wheel frontLeft;
    Wheel frontRight;
    Wheel rearLeft;
    Wheel rearRight;
    Wheel spareInTrunk;

public:
    void wheelsOnCar( list< Wheel > &wheels )
    {
        wheels.push_back( frontLeft );
        wheels.push_back( frontRight);
        wheels.push_back( rearLeft);
        wheels.push_back( rearRight);
    }
    const Wheel & getSpare(){ return spareInTrunk; }
    void setSpare( const Wheel &newSpare ){ spareInTrunk = newSpare; }
    // There are getters and setters for the other wheels too,
    //but they aren't important for this example
};

Тогда я увижу такую функцию:

void wheelsRelatedToCar( Car *aCar, list< Wheel > &wheels )
{
    aCar->wheelsOnCar( wheels );
    wheels.push_back( aCar->getSpare() );
}

Это реальный пример с именами классов и функций, которые были изменены. Почему один хочетwheelsRelatedToCar не быть членом функции автомобиля? В этом реальном примере Car и Wheel были в одной библиотеке. Глобальная функция была определена в исходном файле в конкретном приложении, использующем эту библиотеку, поэтому был выдвинут аргумент, что функция специфична для приложения. Мой ответ состоял в том, что это была совершенно законная операция на автомобиле и принадлежала к классу автомобилей. Есть ли другая перспектива, чтобы смотреть на это (кроме того, кто не предпочитает использовать объектно-ориентированный дизайн)?

Ответы на вопрос(10)

Ваш ответ на вопрос