Как создать статический класс В C++?



как создать статический класс В C++? Я должен быть в состоянии сделать что-то вроде:



cout << "bit 5 is " << BitParser::getBitAt(buffer, 5) << endl;


предполагая, что я создал BitParser класса. Что бы это BitParser определение класса выглядит?

1525   12  

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;
}

вы можете использовать этот код для вызова метода так же, как в вашем примере код.

надеюсь, что это поможет! Овации.

считают решение Мэтта Прайса.

  1. в C++ "статический класс" не имеет смысла. Ближайшая вещь-это класс только со статическими методами и членами.
  2. использование статических методов только ограничит вас.

то, что вы хотите, выражается в семантике 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

    Ничего не найдено.