Делаем классы общедоступными для других классов в C++

Если у меня есть два класса, например, следующим образом:

class A {...}

class B {...}

Если я хочу сделать класс A общедоступным для класса B, мне просто сделать общедоступными члены класса A или я могу просто использовать public class A {...}?

Есть ли способ сообщить классу B, например, что только класс A является для вас общедоступным? Другими словами, могу ли я сделать общедоступные классы A защищенными или закрытыми для других? Или это просто вопрос получения класса (наследования)?

Спасибо.


person Simplicity    schedule 25.01.2011    source источник
comment
вам следует взять хорошую книгу по C++. Есть много тем SO, которые посоветуют вам один.   -  person Alexandre C.    schedule 25.01.2011


Ответы (3)


Существует существенная разница между обнародованием класса и обнародованием его содержимого.

Если вы определяете свой класс во включаемом файле (файле .h), вы делаете свой класс общедоступным. Каждый другой исходный файл, который включает этот включаемый файл, будет знать об этом классе и может, например. иметь указатель на него.

Единственный способ сделать класс закрытым — это поместить его определение в исходный (.cpp) файл.

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

class MyClass
   {
   private:
      MyClass();
      ~MyClass();
      void setValue(int i);
      int getValue() const;
   };

Если это определение помещено во включаемый файл, любой другой источник может ссылаться на этот класс (иметь указатель на него), но, поскольку все методы в классе являются закрытыми, никакой другой источник не может создавать его, уничтожать, устанавливать его значение или получить его значение.

Вы делаете содержимое класса общедоступным, помещая его методы в «общедоступную» часть определения класса, например:

class MyClass
   {
   public:
      MyClass();
      ~MyClass();
      int getValue() const;
   private:
      void setValue(int i);
   };

Теперь каждый может создавать и уничтожать экземпляры этого класса и даже получать значение. Однако установка значения не является общедоступной, поэтому никто не может установить значение (кроме самого класса).

Если вы хотите сделать класс общедоступным только для какого-то другого класса вашего приложения, но не для всего приложения, вы должны объявить этот другой класс другом, например:

class SomeOtherClass;
class MyClass
   {
   friend SomeOtherClass;
   public:
      MyClass();
      ~MyClass();
      int getValue() const;
   private:
      void setValue(int i);
   };

Теперь SomeOtherClass может получить доступ ко всем закрытым методам из MyClass, поэтому он может вызвать setValue, чтобы установить значение MyClass. Все остальные классы по-прежнему ограничены публичными методами.

К сожалению, в C++ нет способа сделать только часть вашего класса общедоступной для ограниченного набора других классов. Итак, если вы сделаете другой класс другом, он сможет получить доступ ко всем закрытым методам. Поэтому ограничьте количество друзей.

person Patrick    schedule 25.01.2011
comment
Когда вы пишете: int getValue() const;, означает ли здесь const: вернуть значение как константу? Спасибо. - person Simplicity; 25.01.2011
comment
Константа означает, что метод не изменит сам экземпляр, поэтому getValue не изменит экземпляр MyClass, для которого вы вызываете getValue. В общем, константное возвращаемое значение (как в const int getValue();) не имеет смысла. Что имеет смысл, так это то, что если вы возвращаете указатель, указатель указывает на константное значение (например, в const char *getName()). - person Patrick; 25.01.2011

Вы можете использовать дружбу.

class A { friend class B; private: int x; };
class B { B() { A a; a.x = 0; // legal };
person Puppy    schedule 25.01.2011
comment
@DeadMG. Это еще одна форма дружбы: класс Б: публичный А? Спасибо. - person Simplicity; 25.01.2011
comment
@ user588855, нет, это наследование. - person Péter Török; 25.01.2011
comment
@DeadMG. Итак, как мы можем сделать публичный класс? Правильно ли использовать ключевое слово public перед именем класса? - person Simplicity; 25.01.2011
comment
@ user588855, в C++ нет ограничений доступности для классов (например, в Java или C#), только для членов класса. Итак, public class X { ... }; недействителен C++. Класс виден другому классу, если вы #import его заголовочный файл. - person Péter Török; 25.01.2011
comment
Как сказал вам DeadMG. Нет, писать public перед ключевым словом class — это не C++. - person Daniel Gehriger; 25.01.2011
comment
@Петер Торок. Когда вы говорите: класс виден другому классу, если вы #импортируете его заголовочный файл, что здесь видно? Я имею в виду, будет ли он общедоступным или защищенным? Или это зависит только от спецификаторов доступа членов класса? Спасибо. - person Simplicity; 25.01.2011
comment
@user588855 user588855, с точки зрения Java, все классы C ++ по умолчанию являются общедоступными, и у вас нет возможности это изменить. - person Péter Török; 25.01.2011
comment
Небольшое замечание: если вы просто хотите сделать все общедоступным, вы можете сделать его структурой, а не классом. Одним из очень немногих различий между классом и структурой является спецификатор доступа по умолчанию для членов. Но да, если вы хотите сделать участников доступными только для определенного класса, вам нужна дружба. - person wich; 25.01.2011
comment
@Петер Торок. Понял, что вы имеете в виду, большое спасибо и спасибо вам всем за ваши ответы. - person Simplicity; 25.01.2011
comment
@Péter Török, когда пользователь 588855 говорит об открытом классе, я думаю, что он / она имеет в виду доступность членов класса. - person wich; 25.01.2011
comment
@который. Итак, могут ли структуры содержать функции? Спасибо. - person Simplicity; 25.01.2011
comment
@ user588855 да, структуры также могут содержать функции-члены, даже виртуальные, конструкторы, перегрузчики операторов и все такое прочее. - person wich; 25.01.2011
comment
@ user588855, @wich, технически да, однако общее соглашение C ++ заключается в использовании структур только как тупых классов данных, то есть без логики. Если вам нужна логика, связанная с вашими данными, вы почти всегда хотите инкапсуляцию, поэтому вы должны объявить ее class (где доступ по умолчанию — private). - person Péter Török; 25.01.2011
comment
@Péter Török #import не является частью стандарта C++. - person UmmaGumma; 25.01.2011

Если B имеет сильную взаимозависимость с A, я предлагаю вам использовать вложенный класс. К счастью, вложенный класс может быть защищенным или закрытым.

class A {
protected:
     // the class A::B is visible from A and its
     // inherited classes, but not to others, just
     // like a protected member.
     class B {
     public:
         int yay_another_public_member();
     };
public:
     int yay_a_public_member();
};
person BatchyX    schedule 25.01.2011