» »

[c++] pomoč pri class composition

[c++] pomoč pri class composition

zhigatsey ::

Živjo,

Zmislil sem si primer, za "kompozicijo razredov", vendar nisem prepričan, če je napisano "dovolj pravilno", saj
se v cpp velikokrat naredi, da je kakšno stvar napisati še bolj pravilno....:)
V glavnem stvar je taka: Ker prihajam iz delphi okolja, kjer sem navajen propertiy-jev, in na te vezane
Set in Get procedure oz. funckije mi je v standardnem c++ malo zaskrbelo kako stvari funkcioniraju tukaj.
Ker bi imel v razredu TPage "lastnost" PageSize sem kot prvo naredil nov privatni statični primerek FPageSize tipa TPageSize.
Ker, pa v standardnem c++-su ni propertiyev ( saj ne vem da obstajajo ), sem pod public sekcijo dodal funkcijo, ki vrača konstantno
referenco na objekt FPageSize, in preko nje dostopam do public metod objekta FPageSize. Sedaj me pa zanima, če je ta način vredu,
v končni fazi bi lahko razred TPage izpeljal iz razreda TPageSize kar bi bilo na tem primeru bolj elegantno izpeljano, vendar pa včasih rabiš tudi tak način. Če lahko podate kakšen komentar, nasvet oz. kako imate to vi rešeno.

Hvala za odgovore

Pa še primer kode:

#include <iostream>
#include <stdlib.h>

using namespace std;

// TPagaSize
class TPageSize
{
    protected: 
        int FWidth;
        int FHeight;
    public:
        TPageSize() : FWidth(0), FHeight(0) {};
        TPageSize(int AWidth, int AHeight) : FWidth(AWidth), FHeight(FHeight) {};
        virtual ~TPageSize() {};
        void SetSize(int AWidth, int AHeight) { FWidth = AWidth; FHeight = AHeight; };
        int GetWidth() const { return FWidth; };
        int GetHeight() const { return FHeight; };
};

// TPage
class TPage
{
     private:
         TPageSize FPageSize;
     public:
         TPage(){ FPageSize.SetSize(0,0); };
         virtual ~TPage(){};
         TPageSize& PageSize() const { return const_cast<TPageSize&>(FPageSize); };        
};

int main(int argc, char *argv[])
{
    TPage page;
    page.PageSize().SetSize(4,7);
    cout << "Width: " << page.PageSize().GetWidth() << endl;
    cout << "Height: " << page.PageSize().GetHeight() << endl;
    
    system("PAUSE");
    return 0;
}

Vesoljc ::


class PageSizeAble
{
   int x,y;
public:
   void  Set(int, int);
   int   GetX();
   int   GetY();
};

class Page: public PageSizeAble
{
};


slaba stran tega je da konstrukcija ter destrukcija pokurita vec casa... pa ce se zacnes ukvarjati z raznimi dinamicnimi casti, pravtako.

se google tip
HAS A, IS A

8-)
Abnormal behavior of abnormal brain makes me normal...

zhigatsey ::

konstrukcija in destrukcija porabi več časa pri izpeljanih razredih mislm aneda itak??, če more jit navzdol oz. navzgor
po hiearhiji. Kar se pa zgornjega primera (mislim primera v mojem postu) tiče je pa potem vse vredu a ne, ker mene
ni toliko skrbela histrost ampak le to kako naj recimo dostopam do objekta FPageSize, recimo prek pointerja ali prek
reference, sej je vse isti k.... samo potem bi moral dinamično kreirat FPageSize, samo sem nekje "prebral", da je v nekaterih
primerih hitrejše da vržeš objekt na sklad kot pa v kopico (v primeru dinamicnega kreiranja)... evo zdej sem pa jst pri histrosti:) ,
ali pa recimo tisti const_cast, ki ga moram uporabiti, če hočem da funckija PageSize vrne konstantno referenco... Sem pač še v taki
fazi pri c-ju da še nisem čisto prepričan ali bi se dalo kakšno stvar bolje napisati...

zhigatsey ::

Aja pa še to , recimo kompozicijo je namesto izpeljave (moje mnenje), bolje uporabiti recimo v tem primeru (iz Delphija:) ) :

Imamo recimo dva razreda TBrush in TPen in obadva imata public metodi SetColor recimo, al ili pa GetColor sej ni važno,
kako bi se potem to izgledalo recimo v tem primeru:

recimo

class TRectangle : : public TBrush, public TPen {
...
};

potem TRectangle podeduje obe metodi z istim imenom (SetColor), mislm ne vem kaj bi bilo potem moram probat, pa še zaradi
tega bi se tukaj reje odločil za kompozicijo, ker ima potem razred bolj "kategorizirane " metode

rectangle.Brush().SetColor() oz.
rectangle.Pen().SetColor

in tudi koda je na prvi pogled bolje razumljiva....

zhigatsey ::

po pomoti napisal dva podpičja, tako mora biti...
class TRectangle : public TBrush, public TPen {
...
};

Vesoljc ::

amm, mislim da ti tega sploh ne prevede, ambigity neki :D
sej je logicno, ne ve ktero klicati. ce se ne motim, so to precej znane tezave (diamond shape inheritance).
vem da lahko naredis kar cel class virtual, potem lahko dela, ampak ne vem natancno :\
Abnormal behavior of abnormal brain makes me normal...

OwcA ::

Ena rešitev je, da povoziš metodo SetColor in znotraj nej eksplicitno kličeš isto metodo kot metodo razreda TBrush ali TPen.

Kompozicija drugače zlgleda vredu, le tisto packanje z const_cast se mi zdi nepottrebno, niti nisem prepričan, da dela kar si si ti zameislil (referencam tako ali tako ne moreš spreminjati kam "kažejo").

P.S. namesto stdlib.h uporabi raje cstdlib
Otroška radovednost - gonilo napredka.

Zgodovina sprememb…

  • spremenilo: OwcA ()

zhigatsey ::

Ja tisti const_cast sem dal zaradi konstantne reference, ki jo vrača funcija, če pa dam const stran pa tudi tega res ni treba ja.

Ok, hvala za odgovore...

OwcA ::

Če vračaš konstantno ne moreš uporabiti metode SetSize(). Če je to namen prav, drugače pa previdno.
Otroška radovednost - gonilo napredka.

Gundolf ::

Kar se tice const_cast:

Vedno lahko naredis iz navadnega reference ali pointerja, referenco ali pointer na konstanten objekt (vsaj v primeru pointerja poznamo se konstanten pointer in konstanten pointer na konstanten objekt;) ). Se pravi ti imas referenco/pointer (ali pa cel objekt) in s tem pravice do vsega sarjenja po objektu, zato naprej lahko podajas referenco/pointer (z istimi pravicami) ali pa referenco/pointer const (s pravicao le do branja objekta). Ce pa imas ti le referenco/pointer const (se pravi na konstanten objekt) pa naprej ne mores podajati navadne reference/pointerja. Razen ce uporabis const_cast. To pa je tudi edina pametna uporaba const_cast-a - da se znebis nadleznega const, na kaksnem objektu, ki ti preprecuje, da bi ga spreminjal.

Se primer:
class Razred {
   int neki;
public:
   void spremeni() {
      neki = neki * neki  + neki - 1.
   }
   int neSpremeni() const {
      return neki;
   };
};

void krNeki(const Razred& neDiraj) {
   // ok
   int a = neDiraj.neSpremeni();
   // ni ok 
   neDiraj.spremeni();
   // je ok, a uporaba le v skrajni sili
   Razred& temp = const_cast<Razred&>(neDiraj)
   temp.spremeni();
}


popravki:
Zakaj tale st.koda vriva prazne vrstice po vsakem komentarju?
Ok pustimo to. Shigatse: prej sem preslabo prebral kodo, zdaj vidim da znas vsaj priblizno uporabljati const_cast :8) . V tvojem primeru pa, ali vracaj Const TPageSize&, pri cemer ga bos lahko le gedal in ne bos mogel spreminjati, ali pa odstrani tisti const pri metodi. Ok, tretja moznost je, da vracas kar TPageSize, ker je tako majhen da se skoraj ne bo poznalo ustvarjanje novega zacasnega objekta, pa se to le v primeru zabitega compilerja, ki ne bo znal optimizirati take kode.

Pac odvisno kaj si zelis. Verjetno hoces imeti get in set metode, iz cesar sledi da bo najbolje vracati referenco na const objekt.

Zgodovina sprememb…

  • spremenil: Gundolf ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Qt/QML zajem podatkov iz podatkovne baze, dobim samo opise fieldov ter prazne vrednos

Oddelek: Programiranje
71750 (1493) windigo
»

[C++] Iskalno drevo implementacija

Oddelek: Programiranje
52316 (1874) eXoo
»

[Java] Nova nit znotraj JPanel.paintComponent()

Oddelek: Programiranje
141975 (1762) alexa-lol
»

[Java] Deljenje in ostanek

Oddelek: Programiranje
143131 (2715) pr2501
»

JAVA kako se premikati v Card layoutu

Oddelek: Programiranje
91248 (1156) matjazx

Več podobnih tem