Вызов функции-члена без создания объекта в C ++ - PullRequest
4 голосов
/ 31 марта 2020

Может кто-нибудь объяснить, почему мы можем вызывать функции-члены stati c, не создавая экземпляр объекта, но мы не можем это сделать в случае не-stati c функций?

Я искал везде, не мог найти объяснения, Вы можете помочь?

Ответы [ 4 ]

4 голосов
/ 31 марта 2020

У вас есть логика c в основном наоборот. Полезно иметь функции, принадлежащие классу, даже если их не нужно вызывать для объекта этого класса. Страуструп не хотел добавлять для этого новое ключевое слово, поэтому он переназначил существующее ключевое слово static, чтобы отличать guish такие методы от обычных методов.

Оглядываясь назад, можно было выбрать и другие варианты. Например, мы могли бы сделать this явным аргументом функции для обычных методов. Но сейчас уже на 30 лет поздно.

2 голосов
/ 31 марта 2020

Почему?

Потому что нам нравится инкапсуляция и модульность, которые мы получаем при использовании объектно-ориентированных шаблонов.

Вы можете рассматривать static функции-члены класса и переменные как способ инкапсуляции того, что в противном случае было бы глобальными функциями и переменными - которые могут конфликтовать.

Ниже не существует большой разницы между простым старым файлом C ++ с некоторыми функциями, объявленными и реализованными в нем, и классом, заполненным только stati c функциями. Разница в том, что мы можем получить чистый доступ к набору функций, прикрепленных к родительскому классу.

Пример: Предположим, вы хотите создать новый класс, такой как MyMediumInteger, и вы хотите, чтобы разработчики определить, какое максимальное количество он может держать. Эта информация применима для каждого экземпляра MyMediumInteger, независимо от состояния переменных закрытого члена. Поэтому имеет смысл раскрыть эту информацию, не заставляя разработчика создавать экземпляр класса. Ваши варианты включают в себя определение чего-то глобального, такого как #define MYMEDIUMINTEGER_MAX ..., которое может столкнуться с определением, имеющим то же имя в другом модуле, или создание функции static, возвращающей максимальный размер, вызываемой аккуратно через

MyMediumInteger::maxSize().

Пример кода:

/***
 * Use a static class member function (or variable)
 */
class MyMediumInteger
{
    public:
        static unsigned long maxSize() { return pow(2, 32) - 1; };
};

auto maxSize = MyMediumInteger::maxSize();

/**
 * Alternative approaches.
 * Note: These could all collide with other #defines or symbols declared/implemented in other modules.
 * Note: These are both independant sources of information related to a class - wouldn't it be nicer if they could just belong to the class instead?
 */

/***
 * Use a #define
 */
#define MYMEDIUMINTEGER_MAX (pow(2, 32) - 1)

auto maxSize = MYMEDIUMINTEGER_MAX;

/**
 * Use a global function or variable
 */
static unsigned long getMyMediumIntegerMaxSize()
{
    return pow(2, 32) - 1;
}

auto maxSize = getMyMediumIntegerMaxSize();

Предупреждение: Stati c переменные и функции-члены имеют некоторые подводные камни: глобальные переменные - поскольку они сохраняются в экземплярах классов, вызов и присвоение им могут вызвать неожиданные побочные эффекты (потому что static переменные-члены изменяются для всех, а не только для вас). Распространенной ошибкой является добавление большого количества статических c функций-членов и переменных для управления - например, статическое ведение списка всех других экземпляров класса, который добавляется в конструктор каждого класса. Часто этот тип кода может быть реорганизован в родительский класс, задачей которого является просто управление экземплярами дочернего класса. Последний подход гораздо более тестируем и сохраняет модульность - например, кто-то другой может прийти и написать другую реализацию кода управления, не добавляя и не переписывая реализацию своего дочернего класса.

Как?

В функциях-членах класса C ++ фактически не хранятся в экземплярах классов, они хранятся отдельно и вызываются для экземпляров классов. Следовательно, несложно представить, как в это вписываются функции stati c - они объявляются так же, как и обычные функции-члены класса, только с ключевым словом static, который говорит: «Мне не нужен класс экземпляр для запуска ". Следствием этого является невозможность доступа к переменным или методам членов класса.

0 голосов
/ 01 апреля 2020

Потому что это то, что static означает : «Я не хочу, чтобы эта функция требовала, чтобы объект работал».

Это функция. Это его определение.

Любой другой ответ будет круглым.

Почему это полезно? Иногда мы хотим иметь возможность «организовать» некоторые данные или служебные программы в наших классах, возможно, для использования внешним кодом или, возможно, для использования нештатными c функциями того же класса. В этом смысле есть некоторое пересечение с пространствами имен.

0 голосов
/ 31 марта 2020

Stati c функция-член не нуждается в указателе "this", она принадлежит классу. Нестатистические c функции нуждаются в указателе «this», чтобы указать, к какому объекту он принадлежит, поэтому сначала нужно создать объект.

...