Read-only property

Odpowiedz Nowy wątek
2012-07-26 18:46
0

Znacie jakiś trick by zadziałała poniższa konstrukcja?

obj.pPointerToSmth->someMethod();

ale tak, by nie można było zmodyfikować wskaźnika w taki sposób:

obj.pPointerToSmth = someAddress;

Nie chcę zwracać wskaźnika za pomocą metody:

obj.pPointerToSmth()->someMethod();

Oczywiście potrzebuję ten wskaźnik ustawić jeden raz po uruchomieniu programu, po utworzeniu obiektu, na który ma ów wskaźnik wskazywać. Ustawiłbym go sobie jakimś setterem (metodą).

Próbowałem wykorzystać:
http://www.codeproject.com/Articles/118921/C-Properties
ale Visual C++ Express 2010 nie akceptuje kodu properties.h, zwraca:

properties.h(5): error C2143: syntax error : missing ')' before '='
properties.h(5): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
properties.h(5): error C2014: preprocessor command must start as first nonwhite space

Przykład:

// ObjectManager to singleton.
#define objManager ObjectManager::GetInstance()
WinMain()
{
    Window pWindow = new Window(...); // Niech Window będzie jakimś oknem windowsowym.
    objManager.SetPtrToWindow(pWindow);

    // Inny kod...

    objManager.pWindow->Show(); // Wyświetlamy okienko.
    objManager.pWindow = NULL; // Próbujemy zmodyfikować wskaźnik. Źle - kompilator powinien nam w tym miejscu uciąć głowę i rzucić rekinom na pożarcie ;-)
}

EDIT: Udało mi się doprowadzić do działania mechanizm z properties.h, ale ten kawałek kodu:

objManager.pWindow = NULL;

spowoduje wyświetlenie błędu dopiero po uruchomieniu kompilacji. W trakcie edytowania kodu IDE nie podkreśli tego jako błąd - macie pomysł jak rozwiązać również ten problem?

edytowany 4x, ostatnio: Goodrock, 2012-07-26 21:59
Pokaż kod klasy, bo ciężko coś doradzić z takich nic nie mówiących urywków. Jak ma być coś niezmienne to używa się słówka const. - Hostel 2012-07-26 22:28
const można użyć w przypadku korzystania z typowych setterów i getterów. Ja natomiast nie chcę zwracać wartości zmiennych za pomocą metody (gettera). W dodatku zwrócona wartość musi być read-only. Kod mojej klasy i tak Ci w niczym nie pomoże bo to pusty, zwyczajny singleton. IDE nie podkreśla tego co opisałem zapewne z powodu użycia tricku jaki znajduje się w properties.h - w poście jest link do artykułu z kodem zawartym w tym pliku + przykłady użycia. - Goodrock 2012-07-26 22:43

Pozostało 580 znaków

2012-07-26 23:03
0

Nie znam specyfiki tego co chcesz osiągnąć, bo jesteś bardzo oszczędny ale const jak wspomniałem wystarcza.

using namespace std;

class Foo
{
public:
    Foo( int _zmienna ) : zmienna( _zmienna )
    {}

    const int zmienna;
};

int main()
{
    Foo t( 8 );
    cout << t.zmienna; // jest ok - jest dostep
    t.zmienna = 3; // kompilator sypie error bo zmienna read-only
    return 0;
}

Jeśli uważasz mój post za wartościowy - daj punkt.
Mój post pomógł Ci rozwiązać problem - zaznacz go.

Pozdrawiam

Pozostało 580 znaków

2012-07-26 23:29
0
class O
{
public:
  void metoda() {}
};
class A
{
private:
  O o;
public:
 O * const wskaznik;
  A(): wskaznik(&o) {}
};
// cos w ten desen. zwroc uwage na const za *

░█░█░█░█░█░█░█░█░█░█░█░
edytowany 2x, ostatnio: krwq, 2012-07-26 23:30

Pozostało 580 znaków

2012-07-26 23:30
0

Owszem Hostel jest to dobre rozwiązanie i wystarczy, jeśli w założeniu zmiennej będziemy przypisywać wartość tylko jeden raz - w trakcie utworzenia obiektu. Wtedy lista inicjalizacyjna jest "jak znalazł". W sumie na chwilę obecną wystarczy mi to rozwiązanie. Jeśli zajdzie potrzeba modyfikacji zmiennej po utworzeniu obiektu to użyję pewnego tricku, który mi przypomniałeś:

void Foo::SetZmienna(int newVal)
{
    *((int*)(&zmienna)) = newVal;
}

int main()
{
    Foo t( 8 );
    cout << t.zmienna;
    t.SetZmienna(9);
    return 0;
}
edytowany 1x, ostatnio: Goodrock, 2012-07-26 23:30

Pozostało 580 znaków

2012-07-26 23:32
0

mozna zrobic tez tak:

private: O o;
public: O
& const const_o;
A(): const_o(o) {}

wtedy o moznesz zmieniac a const_o juz nie


░█░█░█░█░█░█░█░█░█░█░█░
public: O*& const const_o; //warning C4227: anachronism used : qualifiers on reference are ignored - Goodrock 2012-07-26 23:37
sprobuj tak: public: O* const& const_o; - krwq 2012-07-26 23:47

Pozostało 580 znaków

2012-07-26 23:40
0

W sumie jeszcze jedna rzecz trochę psuje estetykę - jeśli takich zmiennych będzie dużo to konstruktor się rozrośnie o mnóstwo parametrów w liście inicjalizacyjnej.

Pozostało 580 znaków

2012-07-26 23:47
0

Owszem, tak może być ale trzeba przyznać że dobrą praktyką jest hermetyzacja danych - czyli używanie set() i get(). Publiczne zmienne są często wynikiem złego zaprojektowania. W końcu jeśli zmienna ma być publiczna to można by użyć struktury a nie klasy.


Jeśli uważasz mój post za wartościowy - daj punkt.
Mój post pomógł Ci rozwiązać problem - zaznacz go.

Pozdrawiam
To zależy. Hermetyzacja wszystkiego "bo tak" to jest chyba jeszcze gorsze podejście. Chronić należy te pola, których nieumiejętne użycie może spowodować niepoprawne lub nieoczekiwane działanie obiektu tej klasy. - Sarrus 2012-07-27 08:56
Na mój gust obiekt powinien zwracać wszystko przez metody - nigdy nie wiadomo czy algorytm nam się nie zmieni. Jak się zmieni to wtedy trzeba będzie dopiero kombinować. - Hostel 2012-07-27 13:38

Pozostało 580 znaków

2012-07-26 23:48
0

proponuje Ci zaczac uzywac C#, tam tego typu rzeczy sa wbudowane w jezyk


░█░█░█░█░█░█░█░█░█░█░█░

Pozostało 580 znaków

2012-07-26 23:56
0

Owszem, tak może być ale trzeba przyznać że dobrą praktyką jest hermetyzacja danych - czyli używanie set() i get(). Publiczne zmienne są często wynikiem złego zaprojektowania. W końcu jeśli zmienna ma być publiczna to można by użyć struktury a nie klasy.

Tak, wiem. Ale chciałem móc używać konstrukcji:

o.pWnd->someMethod();

zamiast:

o.GetPointerToWnd()->someMethod();

ponieważ mój obiekt to singleton, który będzie używany wewnątrz większości innych obiektów, i taka konstrukcja skraca kod.

proponuje Ci zaczac uzywac C#, tam tego typu rzeczy sa wbudowane w jezyk

Wiem, i chciałbym napisać całość w C#, ale nie mogę bo C# nie obsługuje jednej ważnej funkcji, która jest niezbędna w moim programie, dyskutowałem o tym dzisiaj w tym wątku:
http://4programmers.net/Forum/Newbie/201986-kilka_pytan_odnosnie_c
Jak już tam wspomniałem - na upartego da się to obejść, ale to trochę jak bicie kotka za pomocą młotka. Poza tym jeszcze nie jestem gotów na przepisywanie tego do C# bo nie skończyłem aplikacji, a nie wiem jakie jeszcze napotkam problemy - wciąż muszę wykorzystywać reverse-engineering. Nie chcę mieć potem kolejnego zonka, że czegoś tam się nie da łatwo zrobić w C#.

edytowany 1x, ostatnio: Goodrock, 2012-07-26 23:57

Pozostało 580 znaków

2012-07-27 00:00
0

Ja nie widzę tego skrócenia zapisu - zamiast metodę nazwać GetPointerToWnd() możesz w singletonie zrobić zmienną _pWnd oraz metodę zwracającą o nazwie pWnd i wtedy dojdzie Ci tylko nawias.


Jeśli uważasz mój post za wartościowy - daj punkt.
Mój post pomógł Ci rozwiązać problem - zaznacz go.

Pozdrawiam
No właśnie cały czas chodzi mi o te nawiasy ;-) - Goodrock 2012-07-27 00:04
To zrób typedef ;) Teraz będziesz szczęśliwy a po 3 miesiącach może być już mniej radości ;) - Hostel 2012-07-27 00:08
Tzn. do czego użyć typedef? Bo coś nie mogę skojarzyć - może z powodu godziny :) I czemu za 3 miesiące mniej radości? - Goodrock 2012-07-27 00:18
Wycofuje się z typedef - nie tędy droga jednak. Poniosła mnie wyobraźnia ;) - Hostel 2012-07-27 00:39

Pozostało 580 znaków

2012-07-27 08:39
0

Z tego co się orientuję to kompilator Visual C++ obsługuje właściwości. Jest też dostępna darmowa biblioteka stlsoft (http://www.stlsoft.org) udostępniająca właściwości niezależnie od kompilatora.

tylko w trybie C++/CLI - Azarien 2012-07-27 10:10

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0