12 ответов:
Если вы ищете способ применения ключевого слова "static" к классу, например, в C#, то вы не сможете этого сделать без использования управляемого C++.
но внешний вид вашего образца, вам просто нужно создать общедоступный статический метод на Вашем объекте BitParser. Вот так:
BitParser.h
class BitParser { public: static bool getBitAt(int buffer, int bitIndex); // ...lots of great stuff private: // Disallow creating an instance of this object BitParser() {} };BitParser.cpp
bool BitParser::getBitAt(int buffer, int bitIndex) { bool isBitSet = false; // .. determine if bit is set return isBitSet; }вы можете использовать этот код для вызова метода так же, как в вашем примере код.
надеюсь, что это поможет! Овации.
считают решение Мэтта Прайса.
- в C++ "статический класс" не имеет смысла. Ближайшая вещь-это класс только со статическими методами и членами.
- использование статических методов только ограничит вас.
то, что вы хотите, выражается в семантике C++, чтобы поместить свою функцию (для нее и функция) в пространстве имен.
изменить 2011-11-11
в C++нет" статического класса". Ближайшей концепцией будет класс только со статическими методами. Например:
// header class MyClass { public : static void myMethod() ; } ; // source void MyClass::myMethod() { // etc. }но вы должны помнить, что" статические классы " -это хаки в Java-подобных языках (например, C#), которые не могут иметь функции, не являющиеся членами, поэтому они должны вместо этого перемещать их внутри классов как статические методы.
в C++ то, что вы действительно хотите,-это функция, не являющаяся членом, которую вы объявите в пространстве имен:
// header namespace MyNamespace { void myMethod() ; } // source namespace MyNamespace { void myMethod() { // etc. } }почему это?
В C++, пространство имен является более мощным, чем классы для шаблона "Java static method", потому что:
- статические методы имеют доступ к классам private symbols
- частные статические методы по-прежнему видны (если недоступны) для всех, что несколько нарушает инкапсуляцию
- статические методы не могут быть объявлены вперед
- статические методы не могут быть перегружены пользователем без изменения библиотеки заголовок
- нет ничего, что можно сделать с помощью статического метода, который не может быть сделан лучше, чем (возможно, друг) функция-не член в том же пространстве имен
- имена имеют свою собственную семантику (они могут быть объединены, они могут быть анонимными и т. д.)
- etc.
Вывод: Не копируйте/вставляйте этот шаблон Java/C#в C++. В Java/C# шаблон является обязательным. Но в C++, это плохой стиль.
изменить 2010-06-10
был аргумент в пользу статического метода, потому что иногда нужно использовать статическую закрытую переменную-член.
Я немного не согласен, как показано ниже:
решение "статический частный член"
// HPP class Foo { public : void barA() ; private : void barB() ; static std::string myGlobal ; } ;во-первых, myGlobal называется myGlobal, потому что это все еще глобальная частная переменная. Взгляд на источник CPP прояснит, что:
// CPP std::string Foo::myGlobal ; // You MUST declare it in a CPP void Foo::barA() { // I can access Foo::myGlobal } void Foo::barB() { // I can access Foo::myGlobal, too } void barC() { // I CAN'T access Foo::myGlobal !!! }на первый взгляд, факт свободной функции barC не удается получить доступ к Foo:: myGlobal кажется хорошей вещью с точки зрения инкапсуляции... Это круто, потому что кто-то, кто смотрит на ГЭС, не сможет (если не прибегнет к саботажу) получить доступ к Foo::myGlobal.
но если вы посмотрите на него внимательно, вы обнаружите, что это колоссальная ошибка: не только ваша частная переменная должна быть объявлена в HPP (и поэтому видна всему миру, несмотря на то, что она является частной), но вы должны объявить в той же HPP все (как и во всех) функции, которые будут авторизован для доступа к нему !!!
так использование частного статического члена похоже на прогулку на улице в обнаженном виде со списком ваших любовников, татуированных на вашей коже : никто не имеет права прикасаться, но каждый может заглянуть. И бонус: каждый может иметь имена тех, кто уполномочен играть с вашими уборными.
privateдействительно... :- Dрешение "анонимные пространства имен"
анонимные пространства имен будет преимущество в том, чтобы сделать вещи действительно частными.
во-первых, заголовок ГЭС
// HPP namespace Foo { void barA() ; }просто чтобы убедиться, что вы заметили: нет бесполезного объявления Барба или myGlobal. Это означает, что никто, читающий заголовок, не знает, что скрывается за барой.
затем CPP:
// CPP namespace Foo { namespace { std::string myGlobal ; void Foo::barB() { // I can access Foo::myGlobal } } void barA() { // I can access myGlobal, too } } void barC() { // I STILL CAN'T access myGlobal !!! }как вы можете видеть, как и объявление так называемого" статического класса", fooA и fooB все еще могут получить доступ к myGlobal. Но больше никто не может. И никто другой вне этого CPP знает, что fooB и myGlobal даже существуют!
в отличие от "статического класса", идущего по обнаженной с ее адресной книгой, татуированной на ее коже," анонимное " пространство имен полностью одето, которые, казалось бы, лучше инкапсулировал ЕМНИП.
это действительно важно?
если пользователи вашего кода не являются диверсантами (я позволю вам, в качестве упражнения, найти, как можно получить доступ к частной части публичного класса, используя грязный поведение-неопределенный Хак...), что такое
privateиprivate, даже если он виден вprivateраздел класса, объявленного в заголовке.тем не менее, если вам нужно добавить еще одну "частную функцию" с доступом к частному члену, вы все равно должны объявить ее всему миру, изменив заголовок, что является парадоксом, насколько я обеспокоен: если я изменю реализацию моего кода (часть CPP), то интерфейс (часть HPP) не должен меняться. цитировать Леонид :"это инкапсуляция!"
изменить 2014-09-20
когда статические методы классов на самом деле лучше, чем пространства имен с функциями, не являющимися членами?
когда вам нужно сгруппировать функции и передать эту группу в шаблон:
namespace alpha { void foo() ; void bar() ; } struct Beta { static void foo() ; static void bar() ; }; template <typename T> struct Gamma { void foobar() { T::foo() ; T::bar() ; } }; Gamma<alpha> ga ; // compilation error Gamma<Beta> gb ; // ok gb.foobar() ; // ok !!!потому что, если класс может быть параметром шаблона, пространства имен не может.
вы также можете создать бесплатную функцию в пространстве имен:
В BitParser.h
namespace BitParser { bool getBitAt(int buffer, int bitIndex); }В BitParser.cpp
namespace BitParser { bool getBitAt(int buffer, int bitIndex) { //get the bit :) } }В общем, это был бы предпочтительный способ написания кода. Когда нет необходимости в объекте, не используйте класс.
Если вы ищете способ применения ключевого слова "static" к классу, например, в C#
статические классы-это просто компилятор, который держит вас за руку и останавливает вас от написания любых методов/переменных экземпляра.
Если вы просто пишете обычный класс без каких-либо методов/переменных экземпляра, это то же самое, и это то, что вы сделали бы в C++
В C++ нужно создать статическую функцию класса (не статический класс).
class BitParser { public: ... static ... getBitAt(...) { } };вы должны быть в состоянии вызвать функцию с помощью BitParser:: getBitAt() без создания экземпляра объекта, который я предполагаю, является желаемым результатом.
могу ли я написать что-то вроде
static class?нет, согласно в C++11 N3337 типовой проект Приложение C 7.1.1:
изменить: в C ++ статические или внешние спецификаторы могут применяться только к именам объектов или функций. Использование этих спецификаторов с объявлениями типов является незаконным в C ++. В C, эти описатели будут игнорироваться при использовании о объявлениях типов. Пример:
static struct S { // valid C, invalid in C++ int i; };обоснование: Спецификаторы класса хранения не имеют никакого значения при связывании с типом. В C ++, класс члены могут быть объявлены с помощью спецификатора класса статического хранилища. Разрешение спецификаторов класса хранения по типу объявления могут сделать код запутанным для пользователей.
и как
struct,classтакже является объявлением типа.то же самое можно вывести, пройдя по синтаксическому дереву в приложении A.
интересно отметить, что
static structбыло законным в C, но не было никакого эффекта: почему и когда использовать статические структуры в программировании на C?
вы "можете" иметь статический класс В C++, Как упоминалось ранее, статический класс-это тот, который не имеет каких-либо объектов его экземпляра. В C++ это можно получить, объявив конструктор/деструктор как частная. Конечный результат тот же.
в управляемом C++ синтаксис статического класса: -
public ref class BitParser abstract sealed { public: static bool GetBitAt(...) { ... } }... Лучше поздно чем никогда...
это похоже на способ C#сделать это в C++
в файле C#.cs вы можете иметь частный var внутри публичной функции. Когда в другом файле вы можете использовать его, вызвав пространство имен с функцией, как в:
MyNamespace.Function(blah);вот как ИМП то же самое в C++:
SharedModule.h
class TheDataToBeHidden { public: static int _var1; static int _var2; }; namespace SharedData { void SetError(const char *Message, const char *Title); void DisplayError(void); }SharedModule.cpp
//Init the data (Link error if not done) int TheDataToBeHidden::_var1 = 0; int TheDataToBeHidden::_var2 = 0; //Implement the namespace namespace SharedData { void SetError(const char *Message, const char *Title) { //blah using TheDataToBeHidden::_var1, etc } void DisplayError(void) { //blah } }
OtherFile.h
#include "SharedModule.h"OtherFile.cpp
//Call the functions using the hidden variables SharedData::SetError("Hello", "World"); SharedData::DisplayError();
В отличие от других управляемых языков программирования, "статический класс" не имеет смысла в C++. Вы можете использовать статическую функцию-член.
как было отмечено здесь, лучшим способом достижения этого в C++ может быть использование пространств имен. Но так как никто не упомянул
finalключевое слово здесь, я публикую, что прямой эквивалентstatic classиз C# будет выглядеть в C++11 или более поздней версии:class BitParser final { public: BitParser() = delete; static bool GetBitAt(int buffer, int pos); }; bool BitParser::GetBitAt(int buffer, int pos) { // your code }
один случай, когда пространства имен могут быть не столь полезны для достижения "статических классов", - это использование этих классов для достижения композиции по наследованию. Пространства имен не могут быть друзьями классов и поэтому не могут получить доступ к закрытым членам класса.
class Class { public: void foo() { Static::bar(*this); } private: int member{0}; friend class Static; }; class Static { public: template <typename T> static void bar(T& t) { t.member = 1; } };
Comments