switch
blocks are different from if-else
blocks for several reasons:
- The compiler has more freedom to apply optimizations.
-
case
tags have no scope of their own.
To avoid the appearance of inconsistencies and errors difficult to find due to the second characteristic, within each case
they should not declare variables. These could collide with the variables of other case
and their life cycle is not easy to limit.
In order to declare variables within a case
it is necessary to create a scope, which is achieved with the { }
keys. Now, if we review your code:
switch(op){
case 1:
jugador p((char*)"Edwin", (char*)"Tigres", 20 );
jugador p2((char*)"Maria", (char*)"Rapidos", 21 );
jugador p3((char*)"Julio", (char*)"Triunfadores", 30 );
break;
case 2://aquí empieza el problema no se porque
jugador x1(p);
x1.mostrar_jugador();
jugador x2(p2);
x2.mostrar_jugador();
jugador x3(p3);
x3.mostrar_jugador();
break;
We see that you are declaring variables in case 1
that you then try to reuse in case 2
... but of course if op==2
it is impossible that op==1
. In other words: if the case 2
is executed the case 1
is not executed, then the variables p
, p2
and p3
are not going to be declared or initialized and that is not fixed nor even with the keys.
To see it better we will refactor the code slightly:
void func1()
{
// variables locales
jugador p((char*)"Edwin", (char*)"Tigres", 20 );
jugador p2((char*)"Maria", (char*)"Rapidos", 21 );
jugador p3((char*)"Julio", (char*)"Triunfadores", 30 );
}
void func2()
{
jugador x1(p); // ¿Que es p?
x1.mostrar_jugador();
jugador x2(p2); // ¿Que es p2?
x2.mostrar_jugador();
jugador x3(p3); // ¿Que es p3?
x3.mostrar_jugador();
}
// ...
if( op == 1 )
func1();
else if( op == 2 )
func2();
Your program has to request the data of 3 players in option 1 ... and that data must remain alive in successive options, then you should move your declaration to the level of main
.
At this point you have a problem and that is that the default constructor is not implemented. This prevents you from creating objects without specific values. You can solve it using pointers or by enabling the default constructor. The easiest way is to enable the default constructor (consider using std::string
instead of char*
when programming in C ++).
class jugador
{
std::string nombre;
public:
// C++11 en adelante
jugador() = default;
// Standares antiguos C++
jugador()
{ }
};
int main(){ // <-- el tipo de retorno es obligatorio en C++
jugador p, p2, p3;
Although, as we said, you can also use pointers and ignore the default constructor:
-
option C ++ 11, C ++ 14, C ++ 17
int main() {
std::unique_ptr<jugador> p, p1, p2;
// ...
switch(op)
{
case 1:
// C++11 en adelante
p.reset(new jugador("Edwin","Tigres",20));
p2.reset(new jugador("Maria","Rapidos",21));
p2.reset(new jugador("Julio","Triunfadores",30));
// C++14 o C++17
p = std::make_unique<jugador>("Edwin","Tigres",20);
p2 = std::make_unique<jugador>("Maria","Rapidos",21);
p2 = std::make_unique<jugador>("Julio","Triunfadores",30);
break;
case 2:
{ // iniciamos ambito para declarar variables
// Hay que comprobar que los punteros estan inicializados
if( p && p2 && p3 )
{
jugador x1(*p); // p es un puntero
jugador x2(*p2);
jugador x3(*p3);
x1.mostrar_jugador();
x2.mostrar_jugador();
x3.mostrar_jugador();
}
else
std::cout << "No se han introducido datos\n";
break;
}
}
// ...
// No es necesario borrar los punteros, se borran solos
}
-
option C ++ 98, C ++ 03 (old versions)
int main() {
jugador *p = 0, *p1 = 0, *p2 = 0;
// ...
switch(op)
{
case 1:
p = new jugador("Edwin","Tigres",20);
p2 = new jugador("Maria","Rapidos",21);
p2 = new jugador("Julio","Triunfadores",30);
break;
case 2:
{
// Hay que comprobar que los punteros estan inicializados
if( p && p2 && p3 )
{
jugador x1(*p);
jugador x2(*p2);
jugador x3(*p3);
x1.mostrar_jugador();
x2.mostrar_jugador();
x3.mostrar_jugador();
}
else
std::cout << "No se han introducido datos\n";
break;
}
}
// ...
delete p;
delete p2;
delete p3;
}
Final note
I have commented to you that it is preferable to replace char*
with std::string
. I'm telling you because the use you make of the pointers in C ++ is incorrect:
jugador p((char*)"Edwin", (char*)"Tigres", 20 );
// ^^^^^^^ ^^^^^^^
Those two conversions are telling you that you're trying to do something dangerous in C ++. Written strings bareback are, by definition, constants. Modifying one of these chains can result in an undefined behavior of the application (nothing may happen or the chains may be stored in read-only memory and the Operating System will kill your application), not to mention that you may end up treading memory of other variables:
char* cad = (char*)"a"; // cad apunta a un array de 2 bytes
strcpy(cad,"ABCDE"); // ¿Donde metemos los 3 bytes de mas?
C-style solutions would then use dynamic memory to manage the strings or use a fixed-size array ( nombre[100]
) and stick with pointer management and hand string with strcpy
and company.
However, the C ++ solution requires using the class std::string
:
std::string cadena = "a"; // ok
cadena = "ABCDE"; // ok, la clase se encarga de gestionar la memoria del