Read-only property

Read-only property
GO
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 10 lat
0

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

Kopiuj
obj.pPointerToSmth->someMethod();

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

Kopiuj
obj.pPointerToSmth = someAddress;

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

Kopiuj
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:

Kopiuj
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:

Kopiuj
// 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:

Kopiuj
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
HO
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.
GO
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.
HO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 11 lat
  • Postów:283
0

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

Kopiuj
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
KR
  • Rejestracja:prawie 16 lat
  • Ostatnio:6 miesięcy
  • Postów:2514
0
Kopiuj
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
GO
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 10 lat
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ś:

Kopiuj
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
KR
  • Rejestracja:prawie 16 lat
  • Ostatnio:6 miesięcy
  • Postów:2514
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


░█░█░█░█░█░█░█░█░█░█░█░
GO
public: O*& const const_o; //warning C4227: anachronism used : qualifiers on reference are ignored
KR
sprobuj tak: public: O* const& const_o;
GO
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 10 lat
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.

HO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 11 lat
  • Postów:283
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
Sarrus
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.
HO
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ć.
KR
  • Rejestracja:prawie 16 lat
  • Ostatnio:6 miesięcy
  • Postów:2514
0

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


░█░█░█░█░█░█░█░█░█░█░█░
GO
  • Rejestracja:około 17 lat
  • Ostatnio:ponad 10 lat
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:

Kopiuj
o.pWnd->someMethod();

zamiast:

Kopiuj
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
HO
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 11 lat
  • Postów:283
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
GO
No właśnie cały czas chodzi mi o te nawiasy ;-)
HO
To zrób typedef ;) Teraz będziesz szczęśliwy a po 3 miesiącach może być już mniej radości ;)
GO
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?
HO
Wycofuje się z typedef - nie tędy droga jednak. Poniosła mnie wyobraźnia ;)
Rekman
  • Rejestracja:prawie 13 lat
  • Ostatnio:prawie 10 lat
  • Postów:148
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.

Azarien
tylko w trybie C++/CLI
adf88
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 12 lat
1

Sposób implementacji nie powinien być wymuszony fizyczną objętością kodu. Takie podejście jest złe. Liczy się przede wszystkim prostota kodu i niewielka objętość "logiczna". To ile powierzchni ekranu zajmuje kod jest na prawdę sprawą podrzędną (zwłaszcza w czasach wielkich ekranów i mechanizmów uzupełniania składni). Ja rozumiem jakieś makro jeśli coś musi być wielokrotnie powielane etc., ale tak kombinować o jeden nawias? Niedobrze. Wspomniany mechanizm uzupełniania składni sam go będzie wstawiać.

Samemu nieraz próbuję tak bezsensownie kombinować i trzeba się w porę otrząsnąć i postawić do pionu.
Mam nadzieję, że Cię przekonałem. Sam zauważyłeś, że logicznie najlepiej pasuje tu metoda. Więc takiej użyj. Im mniej WTF'owego kodu tym lepiej ;) .

edytowany 6x, ostatnio: adf88
HO
Popieram w całości.
GO
Ok przekonałeś mnie :)
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:dzień
0

Tak, można w C# stworzyć okno o danej nazwie klasy. Jak? CreateWindow().
Całe Windows Forms napisane jest w WinAPI.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.