Constructori multipli pentru clase in Cpp

Stau acum si fac niste modificari / optimizari intr-un proiect, scris, de sigur, de altcineva. Si, surpriza, ca de fiecare data cand faci review ( caci asta faci inainte de a te apuca sa modifici jumate din codul care e acolo ) gasesti ceva care nu e in regula si care te deranjeaza… ceva atat de mic… dar…

Deci, sa trec la tema. Dupa cum se stie in Cpp se pot defini mai multi constructori, astfel, un exemplu:

class Cluster {
private:
  int a;
  int b;
  int c;
  int d;  //aceasta clasa contine foarte multe variabile interne
public:
  //constructorul creeaza clasa pornind de la alta clasa
  Cluster( CAnotherClass *_class );
  // ctor de copiere
  Cluster( Cluster *_cluster );
  // ctor default
  Cluster( );
};

La prima vedere, acest cod pare nevinovat, dar daca te uiti in implementarea constructorilor, ar arata cam astfel :

Cluster::Cluster( CAnotherClass *_c ) : a( _c->a )
    , b( _c->b )
    , c( _c->c )
    , d( _c ->d )
{ /* no code */ }
Cluster::Cluster( Cluster *_c ) : a( _c->a )
    , b( _c->b )
    , c( _c->c )
    , d( _c ->d )
{ /* no code */ }
Cluster::Cluster( ) : a( 0 )
    , b( 0 )
    , c( 0 )
    , d( 0 )
{ /* no code */ }

in fine, mai pui si constructorul de copiere… si ai 100 de linii de cod cu constructori doar.

Partea nasoala apare doar atunci cand vrei sa adaugi / scoti un membru nou din clasa… ceea ce inseamna ca trebui sa modifici toti constructorii… Poate nu e o problema modificarea constructorilor, dar ce faci daca uiti sa faci modificarile intr-un constructor ( daca ai multe surse se poate intimpla foarte des ).

Pentru a face putin ordine in toti constructorii se procedeaza astfel :
1. se alege o functie ( doar una, posibil privata ) care va avea rolul de a atribui valori membrilor privati

Cluster::set( int a, int b, int c, int d );

2. celalti constructori apeleaza doar functia de set definit la punctul 1.

Cluster::Cluster( CAnotherClass *_c )
{
   set( _c->a, _c->b, _c->c, _c->d );
}
Cluster::Cluster( Cluster *_c )
{
   set( _c->a, _c->b, _c->c, _c->d );
}
Cluster::Cluster( )
{
   set( 0, 0, 0, 0 );
}

Prin o astfel de abordare a problemei aveti doar de castigat din urmatoarele motive:

1. atunci cand adaugi un membru nou in clasa, modifici functia set, iar functiile care folosesc functia set o sa dea eroare la compilare ( compilatorul aici e un ajutor pentru tine, iar in celalalt caz trebuie sa modifici manual in fiecare constructor cu posibilitatea ca poti sa omiti undeva modificarile, compilatorul nu iti da nici o eroare, iar la rulare se poate apela un constructor care nu l-ai update-at si care ti-a lasat noua variabila neinitializata ).

2. daca la un moment dat iti dai seama ca o variabila trebuie tratata mai speciala, sa ii faci nishte prelucrari inainte, atunci acest cod nou o sa il scrii doar in functia de set, nu o sa duplici mai apoi codul in toti constructorii.

3. clasa este mult mai bine structurata si ofera o logica celui care o sa ii face review mai tarziu.

cred ca atat.

php – functii cu numar variabil de parametri

Pe langa faptul ca parametrii unei functii php pot avea valori predefinite, precum in exemplul urmator :

<?php
    function say( $what = "nothing" )
    {
        echo $what . "\n";
    }
   
    say( "dude" );
    say( );
?>

mai exista posibilitatea de a defini si functii cu numar variabil de parametri in felul urmator:

<?php
    function say( )
    {
        for ( $i = 0; $i < func_num_args(); $i++ )
            echo func_get_arg( $i ) . " ";
        echo "\n";
    }

    say( "test", "another test" );
?>

In cazul cand se alege aceasta modalitate de a pasa parametrii, accesul la parametri se face cu ajutorul functiilor:

Asta inseamna ca putem defini o functie ce poate lua un numar de parametri intr-un caz si alt numar de parametri in alt caz.

Un exemplu practic unde se poate folosi acest feature al php-ului este la definirea functiilor de SET / GET in clase pentru accesul la anumite date private din clasa respectiva. O functie de SET este o functie ce seteaza o valoare privata in clasa, iar o functie de GET este una care ia valoarea unui membru privat din clasa. Se observa ca functia de set trebuie sa ia cel putin un parametru – fiind noua valoare a membrului

    ///set new value
    public function setValue( $newvalue );

iar functia de GET nu ia nici un parametru, dar trebuie sa returneze valoarea ceruta :

    ///get value
    public function getValue( );

la prima vedere aceste functii pot trai si separat si independente, dar exista posibilitatea sa le comansam in una singura cu ajutorul functiilor cu numar variabil de parametri.
Exemplu:

<?php
    /// definesc clasa A
    class A {
        /// membru privat $_id
        private $_id = 0;
       
        /// functie get/set cu numar variabil de parametri
        public function id( ) {
            if ( func_num_args( ) == 0 ) {
                //daca nu este pasat nici un parametru
                //se returneaza valoarea $_id
                return $this->_id;
            } else {
                //altfel, setez $_id cu primu parametru
                //(restul parametrilor se ignora)
                $this->_id = func_get_arg( 0 );
                return TRUE;
            }
        }
    }
   
    //creez o instanta a clasei A
    $a = new A();
   
    //apelez functia id() ca SET
    $a->id( 5 );
   
    //apelez functia id() ca GET
    echo $a->id();
?>

Prin aceasta modalitate, vom defini in clasa doar o singura functie ceea ce va scadea numarul functiilor declarate in clasa si va face clasa mai usor utilizabila.

atat.

[c++] fopen tip

Atunci cand se aglomereaza mai multe buguri…. se produce o crapaciune ( crash :) ), in rest exista doar noroc.

Acum, am dat de un bug foarte subtil ( care, la mine, se reproduce in combinatie cu alt bug :) ).

Sa exemplific prin cod:

  char *filename = "test.txt";
  FILE* file = fopen( filename, "w" );
  fclose( file );
  /* some code */

Ideea e ca functia fopen poate esua si astfel variabila “file” se seteaza cu NULL si in continuare pasand variabila “file” cu valoare NULL functiei fclose duce la o crapaciune foarte urata… ceea ce ar fi bine de evitat

Corect ar fi :

  char *filename = "test.txt";
  FILE* file = fopen( filename, "w" );
  if ( file )
    fclose( file );
  /* some code */

enjoy.

Cum facem CSS mai dinamic cu PHP

Se presupune ca in timpul apropiat CSS-ul va suferi ceva modificari si va fi posibil de declarat un fel de variabile/constante si va fi mai usor de adapta css-ul de la un proiect la altul. Pina atunci exista o astfel de solutie: utilizam php-ul pentru a face css-ul mai dinamic, mai variabil si mai comod. Php-ul ne permite sa generam fisiere css, modificind contentul cu functia HEADER :

<?php header('content-type: text/css'); ?>

in asa mod, fisierul apelat, va fi considerat de browser ca fiind de tip css. Si asta ne permite sa scrim cod php in viitorul fisier css.
Si de exemplu vom face asa un fisier : style.css.php

<?php
    header('content-type: text/css');
    if ( isset( $_GET['style'] ) ) {
        switch($_GET['style']){
            case 'blue':
                define('T_WIDTH_CELL',90);
                define('T_PADDING_CELL',10);
                define('T_FONT_SIZE',12);
                define('T_FONT_FAMILY','Verdana,Tahoma,"Trebuchet MS",sans-serif');
                define('T_TH_BKG','e1e9ed');
                define('T_TD_BKG','eef3f5');
                define('T_BORDER_C','c9d7df');
                define('T_TH_C','476678');
                define('T_TD_C','80a2b4');
                break;
            case 'orange':             
                define('T_WIDTH_CELL',120);
                define('T_PADDING_CELL',8);
                define('T_FONT_SIZE',11);
                define('T_FONT_FAMILY','"Trebuchet MS",Verdana,Tahoma,sans-serif');
                define('T_TH_BKG','ffb979');
                define('T_TD_BKG','ffc189');
                define('T_BORDER_C','ffa859');
                define('T_TH_C','9a4900');
                define('T_TD_C','fa7700');
                break;
            case 'green':
                define('T_WIDTH_CELL',120);
                define('T_PADDING_CELL',40);
                define('T_FONT_SIZE',15);
                define('T_FONT_FAMILY','"Tahoma,sans-serif,Trebuchet MS",Verdana');
                define('T_TH_BKG','e2e7c9');
                define('T_TD_BKG','e9edd6');
                define('T_BORDER_C','d4dcb0');
                define('T_TH_C','707c37');
                define('T_TD_C','acbb65');
                break;
            default :
                define('T_WIDTH_CELL',120);
                define('T_PADDING_CELL',40);
                define('T_FONT_SIZE',15);
                define('T_FONT_FAMILY','"Tahoma,sans-serif,Trebuchet MS",Verdana');
                define('T_TH_BKG','cacaca');
                define('T_TD_BKG','d2d2d2');
                define('T_BORDER_C','b9b9b9');
                define('T_TH_C','535353');
                define('T_TD_C','868686');
                break;
        }
       
    }else{
        define('T_WIDTH_CELL',90);
        define('T_PADDING_CELL',10);
        define('T_FONT_SIZE',12);
        define('T_FONT_FAMILY','Verdana,Tahoma,"Trebuchet MS",sans-serif');
        define('T_TH_BKG','e1e9ed');
        define('T_TD_BKG','eef3f5');
        define('T_BORDER_C','c9d7df');
        define('T_TH_C','476678');
        define('T_TD_C','80a2b4');
    }
?>

table.my-table{
    padding:0px;
    margin:0px;
    border-collapse:collapse;
}

table.my-table th{
    width: <?php echo T_WIDTH_CELL;?>px;
    padding: <?php echo T_PADDING_CELL;?>px;
    margin: 0px;
    background:#<?php  echo T_TH_BKG; ?>;
    border:1px solid #<?php echo T_BORDER_C; ?>;
    text-align:center;
    font:normal <?php echo T_FONT_SIZE.' '.T_FONT_FAMILY;  ?>;
    color:#<?php echo T_TH_C; ?>;
}


table.my-table td{
    width: <?php echo T_WIDTH_CELL?> px;
    padding: 5px 5px 5px <?php echo T_PADDING_CELL?>px;
    margin: 0px;
    background:#<?php  echo T_TD_BKG; ?>;
    border:1px solid #<?php echo T_BORDER_C; ?>;
    text-align:left;
    font:normal <?php echo T_FONT_SIZE.' '.T_FONT_FAMILY;  ?>;
    color:#<?php echo T_TD_C; ?>;
}

si un fisier index.php :

<html>
<head>
    <title>Test dinamic CSS </title>
    <link rel="stylesheet" href="style.css.php?style=green" type="text/css" media="all" />
</head>
<body>
<center>
    <table cellspacing="0" cellpadding="0" class="my-table">
        <tr>
            <th>Th Division 1</th>
            <th>Th Division 2</th>
            <th>Th Division 3</th>
            <th>Th Division 4</th>
        </tr>
        <tr>
            <td>Td Division 1</td>
            <td>Td Division 2</td>
            <td>Td Division 3</td>
            <td>Td Division 4</td>
        </tr>
        <tr>
            <td>Td Division 1</td>
            <td>Td Division 2</td>
            <td>Td Division 3</td>
            <td>Td Division 4</td>
        </tr>
</table>
<center>
</body>
</html>

si astfel putem sa apelam fisierul style.css.php cu trei parametri : blue, green, orange; care se transmit prin $_GET, in dependenta de care se genereaza un anumit fisier css. Daca intimplator se va gresi parametrul si nu va fi unul din cei enumerati mai sus se va genera un fisier css care va stiliza tabelul my-table in culori gri. Implicit se va apela fisierul css cu parametrul blue. comod nu ?
aici puteti sa scoateti sursele, sursele sunt verificate.

Cum utilizam un font extern in CSS

La realizarea unei pagini web, de cele mai multe ori ma bazez pe designul creat in photoshop. Apoi incep sa formatez template-ul. Si de multe ori am avut o astfel de problema ca selectind in photoshop un anumit font, pentru a scrie un text cu un font mai special, in browser textul nu arata ca in photoshop. Browser-ele utilizeaza alte font-uri. Este de mentionat ca pe pc meu unde acest font este instalat deja in sistemul de operare, pagina arata bine, insa pe alte pc-uri, aceasta pagina utilizeaza alt font, pentru a afisa textul, este vorba despre un font implicit “Arial“. Si din cauza acestei probleme in loc de text utilizam imagini.

Insa, de exemplu, daca este vorba de ceva dinamic, ca un blog este necesar ca titlurile posturilor sa fie scrise mai special, atunci imaginile nu sunt o solutie.

Pentru acesta este un mecanizm special care permite dezvoltatorului sa utilizeze orice font. Trebuie de mentionat ca formatul fontului trebuie sa fie .ttf – pentru browserele Mozilla, Safari, Chrome, Opera; si formatul .eot – pentru IE.

” Aveti nevoie doar de fontul cu formatul .ttf in internet sunt o multime de servicii care transforma din .ttf in .eot

Voi arata un exemplu :

1. includem in proiect fontul .ttf si .eot.

ex:

fonturile vor fi plasate in directoriul resources/fonts (din directoriul parinte).
paginile de stil, (css) in resources/css

paginile html direct in directoriul parinte.

2. Avem urmatoarea structura :

resources/fonts/Bleeding Cowboys.ttf
resources/fonts/Bleeding Cowboys.eot
resources/css/style.css
home.html

Si avem urmatoarele surse :
home.html

<html>
  <head>
  <title> Extern Fonts Enbed</title>
  <link rel="stylesheet"
   href="resources/css/style.css"
   type="text/css"
   media="all" />
  </head>
  <body>
    <br>
    <br>
    <br>
    <br>
      <div class="my-class-silver-big"><center>
        Silver big  extern fonts enbed
      </center></div>
      <div class="my-class-silver-small"><center>
        Silver small  extern fonts enbed
      </center></div>
      <div class="my-class-black-small"><center>
        Black small  extern fonts enbed
      </center></div>
      <div class="my-class-black-big"><center>
        Black big  extern fonts enbed
      </center></div>
  </body>
</html>

Pagina de stil
resources/css/style.css

@font-face {
  font-family:MyFontTitle;
  src:url("../fonts/Bleeding Cowboys.eot");
}

@font-face {
  font-family:MyFontTitle;
  src:url("../fonts/Bleeding Cowboys.ttf");
}

.my-class-silver-small {
  font-family:MyFontTitle;
  font-size:15px;
  color:silver;
}

.my-class-silver-big {
  font-family:MyFontTitle;
  font-size:36px;
  font-weight:bold;
  color:silver;
}

.my-class-black-small {
  font:normal 15px MyFontTitle;
  color:black;
}

.my-class-black-big {
  font:bold 36px MyFontTitle;
  color:black;
}

Si cam asa sa primit rezultatul :

aici download surse

Coding practices

Am inceput sa lucrez la un document de coding practices pe wiki. Scriu despre ce e bine, ce e rau atunci cand programam. Mam focusat mai mult pe C/C++, dar pe viitor poate il voi extinde.

Puteti citi aici ce am scris.

Daca vreti ceva sa adaugati, atunci contactati-ma si ziceti-mi pe codingpractices@foicucod.ro / twitter / comment.

PS: nici pe departe documentu nu e terminat… si urmeaza a se face modificari la el.

enjoy