Учитывая указатель на объект С++, каков предпочтительный способ вызова статической функции-члена?

Скажем, у меня есть:

class A {
public:
    static void DoStuff();

    // ... more methods here ...
};

И позже у меня есть функция, которая хочет вызвать DoStuff:

B::SomeFunction(A* a_ptr) {

Лучше сказать:

    a_ptr->DoStuff();
}

Или это лучше, даже если у меня есть указатель на экземпляр:

    A::DoStuff()
}

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

Ответы

Ответ 1

Я думаю, что я бы предпочел "A:: DoStuff()", так как более ясно, что вызывается статический метод.

Ответ 2

Лучше вызвать статический метод по имени, а не через объект, поскольку он фактически не использует этот объект вообще. В Java такая же проблема существует. Не слишком необычная проблема в Java заключается в следующем:

Thread t = getSomeOtherThread();
t.sleep(1000);

Это компилируется отлично, но почти всегда является ошибкой. Thread.sleep() - статический метод, который заставляет текущий поток спать, а не тот поток, который действует, поскольку код, кажется, подразумевает.

Ответ 3

Я лично предпочитаю соглашение A:: DoStuff(), потому что он сразу же очищает всех, кто читает код, который вызывает вызов статической функции-члена.

Ответ 4

Хотя я согласен, что A:: DoStuff() яснее, и это то, что я бы написал сам, я могу увидеть аргумент для перехода через указатель, который "предположим, что имя класса изменяется". Если класс A становится классом B, нам нужно только обновить имя класса в одном месте (объявление указателя) вместо двух.

Просто мысль...

Ответ 5

Джон Скит открыл мне глаза, почему вы не должны вызывать статический метод с помощью указателя экземпляра. Его пример представлен на Java, но концепция также относится к С++:

Thread t = new Thread(...);
t.start();
t.sleep(1000); // Which thread does it look like this will affect?

Как я прокомментировал, когда я впервые прочитал его ответ: "Пока я не прочитал [Jon post], я подумал о возможности вызова статических методов с помощью ссылки на экземпляр объекта. Теперь я знаю лучше".

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

Ответ 6

Как правило, я делаю A:: DoStuff(); вместо a- > DoStuff(); потому что, может быть, когда-нибудь у функции, в которой я работаю, больше не будет указателя этого экземпляра из-за рефакторинга. Но это общая вещь стиля, в которой вы не должны потерять сон.

Ответ 7

Я видел много вопросов на Java, если люди называли статический метод, используя синтаксис вызова метода экземпляра через объект, а объект на самом деле является подклассом типа переменной, люди задаются вопросом, почему он не вызывает статический метод с тем же именем в подклассе. Тот факт, что они вызывают его через объект, заставляет их думать, что это метод экземпляра, который можно переопределить, и он каким-то образом выполняет динамический поиск в режиме исполнения с использованием типа объекта.

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