Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.56
go
Эксперт C++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
#1

Виртуальный замок - C++

14.01.2013, 13:35. Просмотров 1106. Ответов 5
Метки нет (Все метки)

Доброе утро!
Возникла такая проблема. Допустим, я хочу запретить наследоваться от своего класса другим классам и получить ошибку компиляции(но не пряча при этом конструктор и деструктор в приватную секцию, и не используя С++11).
Для этого я пишу виртуальный замок (virtual lock)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Lock
{
    friend class Foo;
    Lock() { }
    Lock(const Lock&) { }
};
 
class Foo: virtual private Lock
{
 
};
 
class Bar: public Foo
{
 
};
 
int main()
{
    Foo foo;
    Bar bar;
    return 0;
}
http://liveworkspace.org/code/4iyvka$0
Как видим все нормально. Точнее код не скомпилировался, все как мы хотели.

Но вот я немного переделал этот код
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Lock
{
public:
    //friend class Foo;
    Lock() { }
    Lock(const Lock&) { }
};
 
class Foo: virtual private Lock
{
 
};
 
class Bar: public Foo
{
 
};
 
int main()
{
    Foo foo;
    Bar bar;
    return 0;
}
http://liveworkspace.org/code/3GKSYm$0
И он почему-то скомпилировался.

В чем принципиальное различие в этих двух кодах? Подскажите, пожалуйста, что я упускаю...

Добавлено через 5 минут
Т.е. в моем втором примере по прежнему конструктор Lock доступен только Foo.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Lock
{
public:
    //friend class Foo;
    Lock() { }
    Lock(const Lock&) { }
};
 
class Foo: virtual private Lock
{
 
};
 
class Bar: public Foo
{
public:
   Bar()
      :  
      //Lock(),
      Foo()
   {
      
   }
 
};
 
int main()
{
    Foo foo;
    Bar bar;
    return 0;
}
Если раскоментировать вызов конструктора Lock из Bar, то получим ошибку. http://liveworkspace.org/code/4l9OVk$0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
14.01.2013, 13:35     Виртуальный замок
Посмотрите здесь:

Замок - обьясните задачу) - C++
Доброго времени суток. Если кто может, прокомментриуйте пожалуйста код. Хочу разобраться в задаче и сделать сам. Предоставляю код моего...

Кодовый замок, срабатывание по условию - C++
На двери установлен кодовый замок. При наборе на замке натурального числа N (1<=N<=10000) он срабатывает следующим образом: если число N...

Виртуальный operator() - C++
Есть такая иерархия классов. class Network { ...... }; class Server : public Network

Виртуальный контекст - C++ WinAPI
Господа я так понимаю это должно быть виртуальное окно?Вопрос как сделать виртульное окно и то , что мы туда нарисум перенести на наше...

виртуальный деструктор - C++
есть такой пример, у меня вопрос, почему здесь деструктор декларирован просто как деструктор, а не виртуальный (и является ли он в данном...

Виртуальный конструктор - C++
Подскажите, к каких случаях необходимо использовать виртуальный конструктор, и что это такое??

Виртуальный метод - C++
Здравствуйте! Помогите, пожалуйста, найти ошибку в коде. #include "stdafx.h" class Person{ protected: char *name; ...

Виртуальный деструктор - C++
Всем привет! Объясните пожалуйста новичку в ООП, вопрос чисто теоретический поэтому код не прилагаю. Мне сказали что если я в классе...

виртуальный деструтор - C++
нужно ли вообще деструктор класса делать виртуальным? class base_class1 { public: base_class1() { data = new...

Виртуальный метод - C++
class A { virtual void Print()=0; } class B : public A { virtual void Print() { //Печатаем в...

Виртуальный базовый класс - C++
Создать иерархию типов, описывающую - человека, студента, отца семейства и студента-отца семейства. Использовать виртуальные базовые...

виртуальный табличный указатель - C++
виртуальным табличным указателем vptr (указатель на таблицу виртуальных методов класса, которому принадлежит объект) является указатель p...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
lemegeton
2918 / 1347 / 134
Регистрация: 29.11.2010
Сообщений: 2,721
14.01.2013, 15:04     Виртуальный замок #2
Вся суть замка в том, что у класса Lock конструктор приватный.
Когда вы делаете его публичным, вся магия исчезает.
go
Эксперт C++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
14.01.2013, 15:09  [ТС]     Виртуальный замок #3
lemegeton, смотрите третий пример. Там конструктор Lock не вызывается, значит он приватный(мы ведь использовали приватное наследование). Что я упустил?
lemegeton
2918 / 1347 / 134
Регистрация: 29.11.2010
Сообщений: 2,721
14.01.2013, 17:27     Виртуальный замок #4
Цитата Сообщение от go Посмотреть сообщение
Там конструктор Lock не вызывается, значит он приватный
Если что-то не вызывается, это еще не значит, что оно приватное. Кстати, конструктор Lock вызывается, но об этом ниже.

Приватным или публичным что-то может быть объявлено.
Так в языке С++ поля и методы класса (любом класса) объявляются приватными, если не указано обратное с помощью ключевого слова public.
Пример.
C++
1
2
3
4
class Lock {
    Lock() { }                 // приватный конструктор
    Lock(const Lock&) { } // приватный конструктор копирования
};
но
C++
1
2
3
4
5
class Lock {
 public: // вот из-за этого ключевого слова
    Lock() { }                 // публичный конструктор
    Lock(const Lock&) { } // публичный конструктор копирования
};
Помните, что при создании объекта вызываются конструкторы по-умолчанию всех родительских типов перед вызовом конструктора создаваемого объекта.
Пример выведет A B.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
 
class A {
 public:
  A() {
    std::cout << "A" << std::endl;
  }
};
 
class B : public A {
 public:
  B() {
    std::cout << "B" << std::endl;
  }
};
 
 
int main(int argc, char *argv[]) {
 
  B b;
 
  std::cin.peek();
  return 0;
}
... на закуску, фишка приватного наследования только в том, что никто больше не знает о нем.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
 
class A {
 public:
  A() {
    std::cout << "A" << std::endl;
  }
};
 
class B : private A {
 public:
  B() {
    std::cout << "B" << std::endl;
  }
};
 
 
int main(int argc, char *argv[]) {
  srand(time(0));
 
  B *b = new B();
  A *a = b; // фейл, наследование B от А скрыто, "A is an inaccessible base of B" 
 
  std::cin.peek();
  return 0;
}
Добавлено через 6 минут
Ах да, вот еще.
Наследоваться от залоченного таким образом класса можно. Его инстанцировать не выйдет.
go
Эксперт C++
3586 / 1366 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
14.01.2013, 18:02  [ТС]     Виртуальный замок #5
Цитата Сообщение от lemegeton Посмотреть сообщение
... на закуску, фишка приватного наследования только в том, что никто больше не знает о нем.
При виртуально наследовании класс последний в иерархии ответственен за вызов конструктора класса, от которого пошло виртуальное наследование. Вот тому подтверждение
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Lock
{
    friend class Foo;
    Lock() { }
    Lock(const Lock&) { }
};
 
class Foo:  private Lock
{
 
};
 
class Bar: public Foo
{
 
};
 
int main()
{
    Foo foo;
    Bar bar;
    return 0;
}
http://liveworkspace.org/code/82Cr9$0 Конструктор приватный, но фэйла не произошло. Так конструктор класса Lock приватный, но он виден классу Foo.


Цитата Сообщение от lemegeton Посмотреть сообщение
Если что-то не вызывается, это еще не значит, что оно приватное. Кстати, конструктор Lock вызывается, но об этом ниже.
См. выше в этом же посту.

Цитата Сообщение от lemegeton Посмотреть сообщение
public: // вот из-за этого ключевого слова
Цитата Сообщение от go Посмотреть сообщение
class Foo: virtual private Lock
Вот мы его снова сделали для наслелдуемых классов от Foo приватным(т.е. для Bar конструктор Lock приватный).
lemegeton
2918 / 1347 / 134
Регистрация: 29.11.2010
Сообщений: 2,721
14.01.2013, 22:38     Виртуальный замок #6
Цитата Сообщение от go Посмотреть сообщение
При виртуально наследовании класс последний в иерархии ответственен за вызов конструктора класса, от которого пошло виртуальное наследование. Вот тому подтверждение
Совершенно верно, это выскользнуло из моего внимания.
Yandex
Объявления
14.01.2013, 22:38     Виртуальный замок
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru