Как создать статический класс в С++? Я должен был бы сделать что-то вроде:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
Предполагая, что я создал класс BitParser. Каким будет определение класса BitParser?
Как создать статический класс в С++? Я должен был бы сделать что-то вроде:
cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;
Предполагая, что я создал класс BitParser. Каким будет определение класса BitParser?
Если вы ищете способ применения "статического" ключевого слова к классу, например, вы можете в С#, например, вы не сможете использовать Managed С++.
Но внешний вид вашего образца, вам просто нужно создать публичный статический метод для вашего объекта 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;
}
Вы можете использовать этот код для вызова метода точно так же, как ваш пример кода.
Надеюсь, что это поможет! Приветствия.
Рассмотрим решение по цене Matt.
Что вы хотите, выраженное в семантике С++, поставить вашу функцию (для нее есть функция) в пространстве имен.
В С++ нет "статического класса" . Ближайшей концепцией будет класс с только статическими методами. Например:
// header
class MyClass
{
public :
static void myMethod() ;
} ;
// source
void MyClass::myMethod()
{
// etc.
}
Но вы должны помнить, что "статические классы" - это хаки в Java-подобных языках (например, С#), которые не могут иметь нечленовские функции, поэтому вместо этого они перемещают их внутри классов как статические методы.
В С++ то, что вы действительно хотите, это функция, не являющаяся членом, которую вы объявите в пространстве имен:
// header
namespace MyNamespace
{
static void myMethod() ;
}
// source
namespace MyNamespace
{
void myMethod()
{
// etc.
}
}
В С++ пространство имен более мощно, чем классы для шаблона Java static method, потому что:
Заключение: не копируйте и не вставляйте этот шаблон Java/С# в С++. В Java/С# шаблон является обязательным. Но в С++ это плохой стиль.
Был аргумент в пользу статического метода, потому что иногда нужно использовать статическую частную переменную-член.
Я не согласен, как показано ниже:
// 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
// HPP
namespace Foo
{
void barA() ;
}
Просто, чтобы быть уверенным, что вы заметили: нет никакого бесполезного объявления barB и myGlobal. Это означает, что никто, кто читает заголовок, не знает, что скрывается за barA.
Тогда 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 даже существуют!
В отличие от "статического класса" , идущего по обнаженной, с ее адресной книгой, татуированной на ее коже, "анонимное" пространство имен полностью одета, что кажется довольно лучшим инкапсулированным AFAIK.
Если пользователи вашего кода не являются саботажниками (я позволю вам в качестве упражнения найти способ доступа к частной части открытого класса с использованием грязного поведения - undefined hack...), что private
- private
, даже если он отображается в разделе private
класса, объявленного в заголовке.
Тем не менее, если вам нужно добавить еще одну "частную функцию" с доступом к частному члену, вы все равно должны объявить ее во всем мире, изменив заголовок, что является парадоксально, насколько мне известно: Если я изменил реализацию моего кода (часть CPP), тогда интерфейс (часть HPP) НЕ должен меняться. Цитата Leonidas: " Это ENCAPSULATION!"
Когда классы статические методы на самом деле лучше, чем пространства имен с не-членными функциями?
Когда вам нужно объединить функции и передать эту группу в шаблон:
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 class
?
Нет, в соответствии с С++ 11 N3337 стандартный проект Приложение C 7.1.1:
Изменить: в С++ статические или внешние спецификации могут применяться только к именам объектов или функций. Использование этих спецификаторов с объявлениями типов является незаконным в С++. В C эти спецификаторы игнорируются при использовании на объявления типов. Пример:
static struct S { // valid C, invalid in C++ int i; };
Обоснование: Спецификаторы класса хранения не имеют никакого значения при привязке к типу. В С++ класс члены могут быть объявлены с помощью спецификатора класса статического хранилища. Разрешение спецификаторов класса хранения по типу объявления могут сделать код запутанным для пользователей.
И как struct
, class
также является объявлением типа.
То же самое можно сделать, пройдя дерево синтаксиса в приложении А.
Интересно отметить, что static struct
был законным в C, но не имел никакого эффекта: Почему и когда использовать статические структуры в программировании на C?
В С++ вы хотите создать статическую функцию класса (а не статический класс).
class BitParser {
public:
...
static ... getBitAt(...) {
}
};
Затем вы можете вызвать функцию с помощью BitParser:: getBitAt() без создания экземпляра объекта, который, как я полагаю, является желаемым результатом.
У вас может быть статический класс на С++, как упоминалось ранее, статический класс - это тот, у которого нет каких-либо объектов его экземпляра. В С++ это можно получить, объявив конструктор/деструктор закрытым. Конечный результат одинаков.
В управляемом С++ статический класс синтаксиса: -
public ref class BitParser abstract sealed
{
public:
static bool GetBitAt(...)
{
...
}
}
... лучше поздно, чем никогда...
Это похоже на способ С# сделать это в С++
В С# file.cs вы можете иметь private var внутри публичной функции. Когда в другом файле вы можете использовать его, вызвав пространство имен с помощью функции, как в:
MyNamespace.Function(blah);
Здесь, как перевести то же самое в С++:
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();
В отличие от другого управляемого языка программирования, "статический класс" не имеет смысла в С++. Вы можете использовать статическую функцию-член.