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

Запрещение переинициализации public-поля как члена класса - C++

Восстановить пароль Регистрация
 
relationer
33 / 0 / 0
Регистрация: 07.11.2013
Сообщений: 118
20.06.2014, 16:58     Запрещение переинициализации public-поля как члена класса #1
Здравствуйте!

Предположим, у нас есть некий класс, в нем есть public-поле, которое выполняет некоторые служебные функции.
Нужно запретить вызов конструктора поля отовсюду, кроме как из основного класса, т. е. нельзя написать:
C++
1
2
3
4
5
6
7
8
9
10
11
class A
{
public:
    B field;
 
    A() : field { }
    { }
};
/* *** */
A a { };
a.field = B(); // baaad!
При этом, необходимо, чтобы пользователь вызывал неконстантные методы поля.
Объявить в типе поля основной класс как friend и сделать приватный конструктор невозможно - класс универсальный.
Можно сделать объявление поля через const, но тогда почти все внутренние поля придется объявлять как mutable.

Вопрос. Как подобное лучше всего сделать?
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Croessmah
Модератор
Эксперт С++
 Аватар для Croessmah
11845 / 6824 / 771
Регистрация: 27.09.2012
Сообщений: 16,917
Записей в блоге: 2
Завершенные тесты: 1
20.06.2014, 17:36     Запрещение переинициализации public-поля как члена класса #2
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
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
 
 
class A
{
public:
   int x ;
   int get () {
      return x ;
   }
} ;
 
 
template < typename T >
class wrap : public T
{
   friend class Test ;
   wrap operator= ( const wrap & ) { /*...*/ }
   wrap ( const wrap & ) { /*...*/ }
public:
   wrap () : T() { /*...*/ }
} ;
 
 
class Test
{
public:
   wrap<A> d ;
 
   Test ( int x ) {
      d.x = x ;
   }
} ;
 
 
 
 
int main(){
   Test t(40) ;
   A a1 ;
   A a2 ;
   a1=a2 ;
   t.d = a1 ;//Error
   std::cout << t.d.get() << std::endl ;
}
что-то в этом роде? Хотя я и не совсем понял зачем это нужно
relationer
33 / 0 / 0
Регистрация: 07.11.2013
Сообщений: 118
20.06.2014, 19:44  [ТС]     Запрещение переинициализации public-поля как члена класса #3
Ну, этот способ мне не подходит. Слишком напрягает wrap.

Для чего: хочу сделать простую модель событий с использованием а-ля C#. Т. е. что-то типа:
C++
1
Button.onPress += myHandler;
Класс я написал, точнее шаблон, и работает это как-то так:
C++
1
2
3
// button.hpp
struct OnPressEventArgument { int some; }
Event<OnPressEventArgument> OnPress = { };
Т. е. очень лёгкий способ написания событий. Проблема в том, что юзер может написать так:
C++
1
button.OnPress = Event< ... >();
Как это предотвратить?
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
21.06.2014, 01:48     Запрещение переинициализации public-поля как члена класса #4
Сообщение было отмечено автором темы, экспертом или модератором как ответ
C++
1
Button.onPress += myHandler;
Именно так не выйдет, точнее сказать так не принято в С++, ибо в С++ нет свойств, всё через геттеры и сетторы, поэтому будет выглядеть как-то так:
C++
1
Button.addOnPress(myHandler);
И то что приведено в первом посте ошибочно
C++
1
2
public:
    B field;
Открытых членов не должно быть, опять же через сеттеры/геттеры.

Добавлено через 27 минут
Приблизительно так:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <iostream>
#include <vector>
#include <string>
 
class Object
{
    public:
        virtual std::string className(){ return "Object"; };
        virtual ~Object(){};
};
 
typedef void (*Function)(Object* obj);
 
void f1(Object* sender)
{
    std::cout<<sender->className()<<": f1()"<<std::endl;
}
 
void f2(Object* sender)
{
    std::cout<<sender->className()<<": f2()"<<std::endl;
}
 
template <typename FunctionT>
class Event
{
    public:
        void addFunction(FunctionT function)
        {
            if(function)
                functions_.push_back(function);
        }
 
        void invoke(Object* sender)
        {
            for(size_t i=0; i<functions_.size(); ++i)
                 functions_[i](sender);
        }
 
    private:
        std::vector<FunctionT> functions_;
};
 
class Button: public Object
{
    public:
 
        virtual std::string className(){ return "Button"; };
 
        void addOnPress(Function f)
        {
            event_.addFunction(f);
        }
 
        void press()
        {
             event_.invoke(this);
        }
 
    private:
        Event<Function> event_;
};
 
int main()
{
    Button button;
 
    button.addOnPress(f1);
    button.addOnPress(f2);
 
    button.press();
 
    getchar();
    return 0;
}
Yandex
Объявления
21.06.2014, 01:48     Запрещение переинициализации public-поля как члена класса
Ответ Создать тему
Опции темы

Текущее время: 19:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru