9_classes charrez ticona.ppt
TRANSCRIPT
Capitulo 9Capitulo 9Tecnicas: Clases, etc.Tecnicas: Clases, etc.
Bjarne StroustrupBjarne Stroustrupwww.stroustrup.com/Programmingwww.stroustrup.com/Programming
Informacion generalInformacion general
ClasesClases Implementacion e interfazImplementacion e interfaz ConstructoresConstructores Funciones mienbroFunciones mienbro EnumeracionesEnumeraciones
Operador sobrecargado.Operador sobrecargado.
33Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
Idea:Idea: Una clase directamenta representa una idea en el programa.Una clase directamenta representa una idea en el programa.
Si usted puede pensar en "eso" como una entidad separada, es Si usted puede pensar en "eso" como una entidad separada, es posible que podría ser una clase o un objeto de una claseposible que podría ser una clase o un objeto de una clase
Ejemplos: vectores, matrices, flujo de entrada, cadena, FFT, la Ejemplos: vectores, matrices, flujo de entrada, cadena, FFT, la válvula de control, el brazo del robot, controlador de dispositivo, la válvula de control, el brazo del robot, controlador de dispositivo, la imagen en pantalla, el cuadro de diálogo, gráfica, ventana, lectura de imagen en pantalla, el cuadro de diálogo, gráfica, ventana, lectura de temperatura, relojtemperatura, reloj
Una clase es un tipo (definido por el usuario) que especifica Una clase es un tipo (definido por el usuario) que especifica cómo los objetos de este tipo se pueden crear y utilizarcómo los objetos de este tipo se pueden crear y utilizar
En C + + (como en la mayoría de las lenguas modernas), En C + + (como en la mayoría de las lenguas modernas), una clase es el elemento clave para los grandes programasuna clase es el elemento clave para los grandes programas
En C + y muy útil para los más pequeños tambiénEn C + y muy útil para los más pequeños también El concepto fui introducido en simula67El concepto fui introducido en simula67
44Stroustrup/ProgrammingStroustrup/Programming
Miembros y el acceso de miembrosMiembros y el acceso de miembros Una forma de mirar a una claseUna forma de mirar a una clase;;
class X {class X { // // this class’ name isthis class’ name is X X// // data members (they store information)data members (they store information)// // function members (they do things, using the information)function members (they do things, using the information)
};};
EjemploEjemploclass X {class X {public:public:
int m;int m; // // data memberdata memberint mf(int v) { int old = m; m=v; return old; } // int mf(int v) { int old = m; m=v; return old; } // function memberfunction member
};};
X var;X var; // // var var is a variable of type X is a variable of type X var.m = 7;var.m = 7; // // accessaccess var’s var’s data memberdata member m mint x = var.mf(9);int x = var.mf(9); // // callcall var’s var’s member functionmember function mf() mf()
55Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
Una clase es un tipo definido por el usuarioUna clase es un tipo definido por el usuario class X {class X { // // this class’ name isthis class’ name is X X
public:public: // // public members --public members -- that’s the interface to usersthat’s the interface to users//// (accessible by all)(accessible by all)
//// functions functions//// types types//// data (often best kept private) data (often best kept private)
private:private: // // private members --private members -- that’s the implementation detailsthat’s the implementation details//// (accessible by members of this class only)(accessible by members of this class only)
//// functions functions//// types types//// data data
};};66Stroustrup/ProgrammingStroustrup/Programming
Estructura y la clase Los mienbros de la clase son privados por defecto:Los mienbros de la clase son privados por defecto:
class X {class X {int mf();int mf();// // ……
};}; MeansMeans
class X {class X {private:private:
int mf();int mf();// // ……
};}; SoSo
X x;X x; // // variable variable x x of typeof type X Xint y = x.mf();int y = x.mf(); // // error: mf is private (i.e., inaccessible)error: mf is private (i.e., inaccessible)
77Stroustrup/ProgrammingStroustrup/Programming
Estructura y la clase
A struct is a class where members are public by default:A struct is a class where members are public by default:
struct X {struct X {int m;int m;// // ……
};};
MeansMeansclass X {class X {public:public:
int m;int m;// // ……
};};
structstructs are primarily used for data structures where the s are primarily used for data structures where the members can take any valuemembers can take any value
88Stroustrup/ProgrammingStroustrup/Programming
EstructuraEstructura
// // simplest Date (just data)simplest Date (just data) d d
struct Date {struct Date {
int y,m,d;int y,m,d; // // year, month, dayyear, month, day
};};
Date my_birthday;Date my_birthday; // // a a Date Date variable (object)variable (object)
my_birthday.y = 12;my_birthday.y = 12;
my_birthday.m = 30;my_birthday.m = 30;
my_birthday.d = 1950;my_birthday.d = 1950; // // oops! (no day 1950 in month 30)oops! (no day 1950 in month 30)
// // later in the program, we’ll have a problemlater in the program, we’ll have a problem
99
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
StructsStructs
// // simple Date (with a few helper functions for convenience) simple Date (with a few helper functions for convenience) ddstruct Date {struct Date {
int y,m,d;int y,m,d; // // year, month, dayyear, month, day};};
Date my_birthday;Date my_birthday; // // a a Date Date variable (object)variable (object)
// // helper functions:helper functions:
void init_day(Date& dd, int y, int m, int d); // void init_day(Date& dd, int y, int m, int d); // check for valid date and initializecheck for valid date and initialize
void add_day(Date&, int n);void add_day(Date&, int n); // // increase the Date by n daysincrease the Date by n days// …// …
init_day(my_birthday, 12, 30, 1950);init_day(my_birthday, 12, 30, 1950); // // run time error: no day 1950 in month 30run time error: no day 1950 in month 30
1010
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
EstructurasEstructuras
// // dato simpledato simple dd// // garantizar la inicialización de constructorgarantizar la inicialización de constructor//// proporcionar alguna conveniencia de notación proporcionar alguna conveniencia de notación struct Date {struct Date {
int y,m,d;int y,m,d; // // year, month, day year, month, day Date(int y, int m, int d); // Date(int y, int m, int d); // constructor:constructor: check for valid date and initializecheck for valid date and initializevoid add_day(int n);void add_day(int n); // // increase the Date by n daysincrease the Date by n days
};};
// // ……Date my_birthday;Date my_birthday; // // error: error: my_birthdaymy_birthday not initialized not initializedDate my_birthday(12, 30, 1950);Date my_birthday(12, 30, 1950); // // oops! Runtime erroroops! Runtime errorDate my_day(1950, 12, 30);Date my_day(1950, 12, 30); // // okokmy_day.add_day(2);my_day.add_day(2); // // January 1, 1951January 1, 1951my_day.m = 14;my_day.m = 14; // // ouch! (now ouch! (now my_daymy_day is a bad date) is a bad date)
1111
1950
30
12
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
// // simple Date (control access) simple Date (control access) ddclass Date {class Date {
int y,m,d;int y,m,d; // // year, month, dayyear, month, daypublic:public:
Date(int y, int m, int d); // Date(int y, int m, int d); // constructor: verificar fecha válida e inicializarconstructor: verificar fecha válida e inicializar
// // access functions:access functions:void add_day(int n);void add_day(int n); // // increase the Date by n daysincrease the Date by n daysint month() { return m; } int month() { return m; } int day() { return d; }int day() { return d; }int year() { return y; }int year() { return y; }
};};
// // ……Date my_birthday(1950, 12, 30);Date my_birthday(1950, 12, 30); // // okokcout << my_birthday.month() << endl;cout << my_birthday.month() << endl; // // we can read we can read my_birthday.m = 14;my_birthday.m = 14; // // error: error: Date::mDate::m is private is private
1212
1950
30
12
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
La notacion de“dato valido” La notacion de“dato valido” es un caso especial importante de la idea es un caso especial importante de la idea de un valor válidode un valor válido
Tratamos de diseñar nuestros tipos para que los valores están Tratamos de diseñar nuestros tipos para que los valores están garantizados para ser válidogarantizados para ser válidoOr we have to check for validity all the timeOr we have to check for validity all the time
Una regla de lo que constituye un valor válido es llamado un Una regla de lo que constituye un valor válido es llamado un "invariante«"invariante«
La invariante de la fecha ("Fecha debe representar una fecha en el pasado, presente, La invariante de la fecha ("Fecha debe representar una fecha en el pasado, presente, o") es extraordinariamente difícil de precisaro") es extraordinariamente difícil de precisar
Recuerda 28 de febrero de los años bisiestos, etcRecuerda 28 de febrero de los años bisiestos, etc
Si no podemos pensar en una invariante bueno, probablemente se trata Si no podemos pensar en una invariante bueno, probablemente se trata de datos simplesde datos simplesIf so, use a structIf so, use a struct Trate de pensar en una buena invariantes para las clasesTrate de pensar en una buena invariantes para las clases Que le ahorra errores en el codigoQue le ahorra errores en el codigo
1313
ClasesClases
// // simple Date (some people prefer implementation details last) simple Date (some people prefer implementation details last) d dclass Date {class Date {public:public:
Date(int y, int m, int d); // Date(int y, int m, int d); // constructor:constructor: check for valid date and initializecheck for valid date and initializevoid add_day(int n); //void add_day(int n); // increase the Date by n daysincrease the Date by n daysint month();int month();// // ……
private:private:int y,m,d;int y,m,d; // // year, month, dayyear, month, day
};};
Date::Date(int yy, int mm, int dd)Date::Date(int yy, int mm, int dd) // // definition; note :: “member definition; note :: “member of”of”:y(yy), m(mm), d(dd) { /* :y(yy), m(mm), d(dd) { /* …… */ }; */ }; // // note: member initializersnote: member initializers
void Date::add_day(int n) { /*void Date::add_day(int n) { /* …… */ }; */ }; // // definitiondefinition
1414
1950
30
12
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
// // simple Date (some people prefer implementation details last) simple Date (some people prefer implementation details last) ddclass Date {class Date {public:public:
Date(int y, int m, int d); // Date(int y, int m, int d); // constructor:constructor: check for valid date and initializecheck for valid date and initializevoid add_day(int n); //void add_day(int n); // increase the Date by n daysincrease the Date by n daysint month();int month();// …// …
private:private:int y,m,d;int y,m,d; // // year, month, dayyear, month, day
};};
int month() { return m; } //int month() { return m; } // error: forgot error: forgot Date::Date:: // // this this month() month() will be seen as a global will be seen as a global
functionfunction //// not the member function, can’t access not the member function, can’t access
membersmembers
int Date::season() { /* int Date::season() { /* …… */ } */ } //// error: no member called error: no member called seasonseason1515
1950
30
12
Date:my_birthday: y
m
Stroustrup/ProgrammingStroustrup/Programming
ClssesClsses
// // simple Date (what can we do in case of an invalid date?)simple Date (what can we do in case of an invalid date?)class Date {class Date {public:public:
class Invalid { };class Invalid { }; // // to be used as exceptionto be used as exceptionDate(int y, int m, int d);Date(int y, int m, int d); // // check for valid date and initializecheck for valid date and initialize// …// …
private:private:int y,m,d;int y,m,d; // // year, month, dayyear, month, daybool checkbool check((int y, int m, int d);int y, int m, int d); // // is (y,m,d) a valid date?is (y,m,d) a valid date?
};};
Date::Date:: Date(int yy, int mm, int dd)Date(int yy, int mm, int dd): y(yy), m(mm), d(dd): y(yy), m(mm), d(dd) // // initialize data membersinitialize data members
{{if (!check(y,m,d)) throw Invalid();if (!check(y,m,d)) throw Invalid(); // // check for validitycheck for validity
}}1616Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
porque ambos con las distincion de publico/prinvado?porque ambos con las distincion de publico/prinvado? Porque no hacer todo publico?Porque no hacer todo publico?
Para proveer una buena interfazPara proveer una buena interfaz Informacion y funciones pueden ser privadosInformacion y funciones pueden ser privados
Para mantener una invariantePara mantener una invariante Solo unas funciones deben acceder a la informacionSolo unas funciones deben acceder a la informacion
Para facilitar la depuraciónPara facilitar la depuración Sólo un conjunto fijo de funciones puede acceder a los Sólo un conjunto fijo de funciones puede acceder a los
datosdatos (known as the “round up the usual suspects” technique)(known as the “round up the usual suspects” technique)
Para permitir el cambio de representacionPara permitir el cambio de representacion Tu solo necesitas cambiar un conjunto de funcionesTu solo necesitas cambiar un conjunto de funciones Tu realmente no sabes quien esta usando un mienbro publicoTu realmente no sabes quien esta usando un mienbro publico
EnumeracionesEnumeraciones
Una Una enumenum (enumeracion) es un simple tipo definido, (enumeracion) es un simple tipo definido, especificando el conjunto de valores(enumerators)especificando el conjunto de valores(enumerators)
por ejemplo:por ejemplo:enum Month {enum Month {
jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, decjan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec};};
Month m = feb;Month m = feb;m = 7;m = 7; // // error: can’t assignerror: can’t assign int int toto Month Monthint n = m;int n = m; // // ok: we can get the numeric value of aok: we can get the numeric value of a Month MonthMonth mm = Month(7);Month mm = Month(7); // // convertconvert int int to to Month Month (unchecked)(unchecked)
1818Stroustrup/ProgrammingStroustrup/Programming
EnumeracionesEnumeraciones
Lista simple de constantes:Lista simple de constantes:enum { red, green };enum { red, green }; // // the the enum { }enum { } doesn’t define a scope doesn’t define a scopeint a = red;int a = red; // // red red is available hereis available hereenum { red, blue, purple };enum { red, blue, purple }; //// error: error: redred defined twice defined twice
Tipo de lista de constanteTipo de lista de constante ssenum Color { red, green, blue, /* enum Color { red, green, blue, /* …… */ }; */ };
enum Month { jan, feb, mar, /*enum Month { jan, feb, mar, /* …… */ }; */ };
Month m1 = jan;Month m1 = jan;Month m2 = red;Month m2 = red; // // errorerror red red isn’t aisn’t a Month MonthMonth m3 = 7;Month m3 = 7; // // errorerror 7 7 isn’t aisn’t a Month Monthint i = m1;int i = m1; // // ok: an enumerator is converted to its value,ok: an enumerator is converted to its value, i==0 i==0
1919Stroustrup/ProgrammingStroustrup/Programming
Enumeraciones – ValoresEnumeraciones – Valores
Por defectoPor defecto//// the first enumerator has the value 0,the first enumerator has the value 0,// // the next enumerator has the value “one plus the value of thethe next enumerator has the value “one plus the value of the//// enumerator before it”enumerator before it”enum { horse, pig, chicken };enum { horse, pig, chicken }; // // horse==0, pig==1, horse==0, pig==1,
chicken==2chicken==2
Tu puedes controlar las numeracionesTu puedes controlar las numeracionesenum { jan=1, feb, march /* enum { jan=1, feb, march /* …… */ }; */ }; // // feb==2, march==3feb==2, march==3enum stream_state { good=1, fail=2, bad=4, eof=8 };enum stream_state { good=1, fail=2, bad=4, eof=8 };int flags = fail+eof;int flags = fail+eof; // // flags==10flags==10stream_state s = flags;stream_state s = flags; // // error: can’t assignerror: can’t assign anan int int to ato a stream_state stream_statestream_state s2 = stream_state(flags);stream_state s2 = stream_state(flags); // // explicit conversion (be explicit conversion (be
careful!)careful!)
2020Stroustrup/ProgrammingStroustrup/Programming
ClasesClases// // simple Date (use Month type)simple Date (use Month type)class Date {class Date {public:public:
enum Month {enum Month {
jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, decjan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec};};Date(int y, Month m, int d); // Date(int y, Month m, int d); // check for valid date and initializecheck for valid date and initialize// …// …
private:private:int y;int y; // // yearyearMonth m;Month m;int d;int d; //// dayday
};};
Date my_birthday(1950, 30, Date::dec);Date my_birthday(1950, 30, Date::dec); // // error: 2error: 2ndnd argument not a argument not a MonthMonth
Date my_birthday(1950, Date::dec, 30);Date my_birthday(1950, Date::dec, 30); // // okok 2121
1950
30
12
Date:
my_birthday: y
m
d
Stroustrup/ProgrammingStroustrup/Programming
ConstConst
class Date {class Date {public:public:
// // ……int day() const { return d; }int day() const { return d; } // // constconst member: can’t modify member: can’t modifyvoid add_day(int n);void add_day(int n); // // non-non-constconst member: can modify member: can modify// // ……
};};
Date d(2000, Date::jan, 20);Date d(2000, Date::jan, 20);const Date cd(2001, Date::feb, 21);const Date cd(2001, Date::feb, 21);
cout << d.day() << " – " << cd.day() << endl;cout << d.day() << " – " << cd.day() << endl; //// okokd.add_day(1);d.add_day(1); //// okokcd.add_day(1);cd.add_day(1); // // error:error: cd cd is ais a const const
2222Stroustrup/ProgrammingStroustrup/Programming
ConstConst
////
Date d(2004, Date::jan, 7);Date d(2004, Date::jan, 7); // // a variablea variable
const Date d2(2004, Date::feb, 28);const Date d2(2004, Date::feb, 28); // // a constanta constant
d2 = d;d2 = d; // // error:error: d2 d2 is is constconst
d2.add(1);d2.add(1); // // error error d2d2 is is const const
d = d2;d = d2; // // finefine
d.add(1);d.add(1); // // finefine
d2.f();d2.f(); // // should work if and only ifshould work if and only if f() f() doesn’t modifydoesn’t modify d2 d2
// // how do we achieve that? (say that’s what we want, of course)how do we achieve that? (say that’s what we want, of course)
2323Stroustrup/ProgrammingStroustrup/Programming
Const funciones mienbroConst funciones mienbro// // Distinguish between functions that can modify (mutate) objectsDistinguish between functions that can modify (mutate) objects
// // and those that cannot (“const member functions”)and those that cannot (“const member functions”)
class Date {class Date {
public:public:
// …// …
int day() const;int day() const; // // get (a copy of) the day get (a copy of) the day
// …// …
void add_day(int n);void add_day(int n); // // move the date n days forwardmove the date n days forward
// …// …
};};
const Date dx(2008, Month::nov, 4);const Date dx(2008, Month::nov, 4);
int d = dx.day();int d = dx.day(); // // finefine
dx.add_day(4);dx.add_day(4); // // error: can’t modify constant (immutable) dateerror: can’t modify constant (immutable) date
2424Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
Que hace una interface buena?Que hace una interface buena? MinimoMinimo
Los mas pequeño posible.Los mas pequeño posible. CompletoCompleto
Y no pequeñoY no pequeño Tipo seguroTipo seguro
Tener cuidado de confundir el orden de los argumentosTener cuidado de confundir el orden de los argumentos Const correctConst correct
2525Stroustrup/ProgrammingStroustrup/Programming
ClasesClases
Operaciones EscencialesOperaciones Escenciales Default constructor (defaults to: nothing)Default constructor (defaults to: nothing)
No default if any other constructor is declaredNo default if any other constructor is declared Copy constructor (defaults to: copy the member)Copy constructor (defaults to: copy the member) Copy assignment (defaults to: copy the members)Copy assignment (defaults to: copy the members) Destructor (defaults to: nothing)Destructor (defaults to: nothing)
Por ejemploPor ejemploDate d;Date d; // // error: no default constructorerror: no default constructorDate d2 = d;Date d2 = d; // // ok: copy initialized (copy the elements)ok: copy initialized (copy the elements)d = d2;d = d2; // // ok copy assignment (copy the elements)ok copy assignment (copy the elements)
2626Stroustrup/ProgrammingStroustrup/Programming
Interfaces y “funciones auxiliares”Interfaces y “funciones auxiliares”
Mantener una interfaz de clase (el conjunto de Mantener una interfaz de clase (el conjunto de funciones publicas)funciones publicas) Simplifica el entendimientoSimplifica el entendimiento Simplifies debuggingSimplifies debugging Simplifica el mantenimientoSimplifica el mantenimiento
Cuando mantenemos la interfaz de clase simple y Cuando mantenemos la interfaz de clase simple y minimalista, necesitamos extra "funciones minimalista, necesitamos extra "funciones axiliares " fuera de la clase (que no son miembros axiliares " fuera de la clase (que no son miembros las funciones)las funciones)
E.g. == (equality) , != (inequality)E.g. == (equality) , != (inequality) next_weekday(), next_Sunday()next_weekday(), next_Sunday()
2727Stroustrup/ProgrammingStroustrup/Programming
Funciones auxiliaresFunciones auxiliares
Date next_Sunday(const Date& d)Date next_Sunday(const Date& d){{
// // access access d d using using d.day(), d.month(), d.day(), d.month(), andand d.year() d.year()// // make newmake new Date Date to returnto return
}}
Date next_weekday(const Date& d) { /* Date next_weekday(const Date& d) { /* …… */ } */ }
bool operator==(const Date& a, const Date& b)bool operator==(const Date& a, const Date& b){{
return a.year()==b.year()return a.year()==b.year()&& a.month()==b.month()&& a.month()==b.month()&& a.day()==b.day();&& a.day()==b.day();
}}
bool operator!=(const Date& a, const Date& b) { return !(a==b); }bool operator!=(const Date& a, const Date& b) { return !(a==b); }
2828Stroustrup/ProgrammingStroustrup/Programming
Operador SobrecargadoOperador Sobrecargado
Tu puedes definir tambien todo C++ operadores Tu puedes definir tambien todo C++ operadores una clase o operandos numerativosuna clase o operandos numerativos Eso es llamado “operador sobrecargado”Eso es llamado “operador sobrecargado”
enum Month {enum Month {jan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, decjan=1, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec
};};
Month operator++(Month& m)Month operator++(Month& m) // // prefix increment prefix increment operatoroperator
{{m = (m==dec) ? jan : Month(m+1);m = (m==dec) ? jan : Month(m+1); // // “wrap around”“wrap around”return m;return m;
}}
Month m = nov;Month m = nov;++m;++m; // // m m becomesbecomes dec dec++m;++m; // // m m becomesbecomes jan jan 2929Stroustrup/ProgrammingStroustrup/Programming
Operador sobrecargadoOperador sobrecargado
Tu puedes definir solo operadores existentesTu puedes definir solo operadores existentes E.g.E.g., , + - * / % [] () ^ ! & < <= > >=+ - * / % [] () ^ ! & < <= > >=
Tu puedes definir operadores solo con sus valores Tu puedes definir operadores solo con sus valores convencionales de operando.convencionales de operando. E.g.E.g., no unary , no unary <=<= (menor igual) and no binary (menor igual) and no binary !! (no) (no)
Un operador sobrecargado debe tener`por lo menos un uso Un operador sobrecargado debe tener`por lo menos un uso definido como operador.definido como operador. int operator+(int,int);int operator+(int,int); //// error: you can’t overload built-in + error: you can’t overload built-in + Vector operator+(const Vector&, const Vector &);Vector operator+(const Vector&, const Vector &); //// ok ok
Consejo (No es una regla):Consejo (No es una regla): Sobrecargar operadores solo con su significado convencionalSobrecargar operadores solo con su significado convencional ++ debe ser adicion, debe ser adicion, ** es multiplicacion, es multiplicacion, [][] es acceso, es acceso, ()() llamada, etc. llamada, etc.
Consejo (no es una regka):Consejo (no es una regka): No sobrecargues a menos que sea necesario.No sobrecargues a menos que sea necesario.
3030Stroustrup/ProgrammingStroustrup/Programming