Llamamiento a entendidos en C++, ayuda!

buenas a todos eolianos aficionados/profesionales de la programacion. resutla que tnego que entregar un pequeño documento antes de este domingo y no consigo resolver estas preguntas:

Cuestión 3: ¿Es posible declarar en la parte privada de una clase objetos de otra clase? ¿existe alguna limitación o requisitos a cumplir?

he estado informandome y creo que para ello necesito usar las herencias de objetos, pero es que por mas que veo ejemplos de ello, al parecer la clase derivada de la clase base tiene que agregarla en su parte publica, y yo quiero que sea en la privada, podria cambiarse sin problemas o es otra cosa distinta a la herencia lo que me pide esa pregunta?

Ejemplo:

class vehiculo_rodante {

int ruedas;
int pasajeros;

public:
void set_ruedas(int num) { ruedas = num;}
int get_ruedas() { return ruedas; }
void set_pasajeros(int num) { pasajeros = num; }
int get_pasajeros() { return pasajeros; }

};

class camion : public vehiculo_rodante {
int carga;

public:
void set_carga(int size) { carga = size; }
int get_carga() { return carga; }
void mostrar();

};


Un saludo!
Yo C++ no sé, pero si sé Java, que también es orientado a objetos. (son las mismas palabras reservadas por lo que estoy viendo...)

Todavía no controlo demasiado bien el tema de objetos y tal, pero yo creo que si se podría. Yo he creado clases dentro de las cuales alguna variable de instancia era otro objeto y no daba fallos, así que supongo que siendo privada esa variable tendría que funcionar...

De todas formas te subo el hilo

Un saludo.
La pregunta en negrita se refiere a eso?

tengo una clase objeto1 y quiero crear una clase objeto2 que sea:

class objeto2
{

int ruedas;
objeto1 objeto;

public:
void set_ruedas(int num) { ruedas = num;}
int get_ruedas() { return ruedas; }
void set_pasajeros(int num) { pasajeros = num; }
int get_pasajeros() { return pasajeros; }
void set_objeto(objeto1 o) { objeto = o; }
objeto1 get_objeto() { return objeto; }
}

Si es eso, a menos que no vaya muy mal claro que se puede. El requisito a cumplir es un include en objeto2 de objeto1 (para que sepa que exista), y evidentemente tendras que sobrecargar el operador de asignacion si te hace falta hacer el objeto = o del ejemplo.

PERO
Lo que tu pones es un ejemplo de herencia (bien usada) pero que para mi no responde en nada la pregunta. Con la herencia tienes algo que es una clase base "mas compleja". Es decir, hace lo mismo que la base y mas cosas. Y lo otro es una clase formada de otras clases (en un paradigma orientado a objetos "puro" todo es una clase, INT es la clase de enteros. En C++ no es asi y hay tipos primitivos, pero bueno)

Me explico un poco mal, pero a ver si te sirve de algo :p
Si se puede.

Requisitos a cumplir:
- Si lo que declaras son punteros tiene q poner la predeclaracion, si son objetos que se almacenan en el stack ( amos que no son punteros ) tienes que poner el include

No hay mucho mas ahi creo yo
urosidoki escribió:Si se puede.

Requisitos a cumplir:
- Si lo que declaras son punteros tiene q poner la predeclaracion, si son objetos que se almacenan en el stack ( amos que no son punteros ) tienes que poner el include

No hay mucho mas ahi creo yo


Con un include no lo resuelves siempre? (aunque no se si es menos correcto o no)
ummm....voy entendiendo lo que me decis, pero no se si es q la preugnta es de mas nivel de lo que damos en clase, pero eso de meter un include dentro de una clase....nosotros solo usamos include para linkear de un .h o para librerias, pero dentro de clases no :-? por eso me extraña un poco esa ultima linea dentro de public en el codigo de darix. La predaclaracion os referis a lo que ha peustod arix: "objeto1 objeto;" ?

Podriais explicarme un poco ese aspecto?

Un saludo!
Mike-Ville escribió:nosotros solo usamos include para linkear de un .h o para librerias, pero dentro de clases no :-?

Haces el include del .h de la clase que quieras usar en la nueva clase que estás creando.

En el ejemplo de darix:

#include "objeto1.h" (suponiendo que objeto1 está declarado en el archivo objeto1.h)

class objeto2
{

int ruedas;
objeto1 objeto;

public:
void set_ruedas(int num) { ruedas = num;}
int get_ruedas() { return ruedas; }
void set_pasajeros(int num) { pasajeros = num; }
int get_pasajeros() { return pasajeros; }
void set_objeto(objeto1 o) { objeto = o; }
objeto1 get_objeto() { return objeto; }
}

¿Vosotros declaráis todas las clases en un mismo archivo o es que no usáis clases con atributos que sean otras clases creadas por vosotros?

Mike-Ville escribió:La predaclaracion os referis a lo que ha peustod arix: "objeto1 objeto;" ?

No tengo ni idea de a qué le está llamando predeclaración, pero lo de "objeto1 objeto;" es para añadirle un atributo a la clase objeto2 (un atributo de la clase objeto1 que se llama objeto).

Respecto a la pregunta, yo creo que se refiere al ejemplo de darix, que hay que poner el include para poder usar un objeto de otra clase y la limitación que yo conozco es que no puede haber ciclos (objeto1 tiene un include de objeto2 y objeto2 uno de objeto1), aunque esto se puede salvar, no recuerdo ahora mismo cómo (sí recuerdo alguna cosa, pero por no liar más el tema... xD).
darix2006 escribió:
urosidoki escribió:Si se puede.

Requisitos a cumplir:
- Si lo que declaras son punteros tiene q poner la predeclaracion, si son objetos que se almacenan en el stack ( amos que no son punteros ) tienes que poner el include

No hay mucho mas ahi creo yo


Con un include no lo resuelves siempre? (aunque no se si es menos correcto o no)


Si, pero si vas a usar pointers no hace falta meter el include, es mala practica eso, es un coñazo explicarlo, pero basicamente no es wena practica hacer includes en los .h a no ser que sea necesario, si puedes usar la predeclaracion porque vas a usar pointers mejor :D
urosidoki escribió:Si, pero si vas a usar pointers no hace falta meter el include, es mala practica eso, es un coñazo explicarlo, pero basicamente no es wena practica hacer includes en los .h a no ser que sea necesario, si puedes usar la predeclaracion porque vas a usar pointers mejor :D

¿Podrías decirme qué es la predeclaración y/o dónde encontrar información sobre lo que comentas?
Mira un ejemplo completo:

main.cpp
#include <iostream>
#include "clase2.h"
using namespace std;

int main(void)
{
clase2 *c;
int x;
cout << "hola" << endl;
cin >> x;
c = new clase2(x);
cout << c->get() << endl;
cin >> x;
return 0;
}

clase1.h
#pragma once

class clase1
{
private:
int x;
public:
clase1(int n);
~clase1(void);
inline int getX() { return x; }
};

clase1.cpp
#include "clase1.h"

clase1::clase1(int n)
{
x=n;
}

clase1::~clase1(void)
{
}

clase2.h
#pragma once
#include "clase1.h"

class clase2
{
private:
clase1 *clase;
public:
clase2(int x);
~clase2(void);
inline int get() { return clase->getX(); };
};

clase2.cpp
#include "clase2.h"

clase2::clase2(int x)
{
clase = new clase1(x);
}

clase2::~clase2(void)
{
}
kNo escribió:
urosidoki escribió:Si, pero si vas a usar pointers no hace falta meter el include, es mala practica eso, es un coñazo explicarlo, pero basicamente no es wena practica hacer includes en los .h a no ser que sea necesario, si puedes usar la predeclaracion porque vas a usar pointers mejor :D

¿Podrías decirme qué es la predeclaración y/o dónde encontrar información sobre lo que comentas?



/// myclass.h

class MySecondClass;

class MyClass
{
public:
...
protected:
...
private:
MySecondClass* mMySecondClass;
};

Eso es la predeclaracion. El compilador ya sabe que tienes un tipo de dato X que a fin de cuentas sera simplemente un puntero, con lo cual no necesita informacion del tamaño del tipo de dato porque es un pointer, y por eso no hace falta hacer el include del MySecondClass

#include "mysecondclass.h" ---> mal si vas a usar pointers ( mala practica me refiero )
class MySecondClass; ---> buena practica
Vale, entre eso y lo que he visto por ahí ya tengo una idea bastante clara, procuraré usarlo a partir de ahora (evitar dependencias y reducir el tiempo de compilación, vale la pena). Gracias.
kNo escribió:Vale, entre eso y lo que he visto por ahí ya tengo una idea bastante clara, procuraré usarlo a partir de ahora (evitar dependencias y reducir el tiempo de compilación, vale la pena). Gracias.


Si, es por eso mismo, reduces el tiempo de compilacion y hasta creo ( no stoy seguro ) que el tamaño del binario es mas pequeño
urosidoki, dices que si usas punteros es mejor usar eso.

Pero mi ejemplo funcionaria sin el include?
muchas gracias a todos chicos por la ayuda, ya he visto la luz al final del tunel, con lo que me habeis escrito ya se responder, muchisimas gracias de nuevo.

Un saludo!

EDIT: por cierto, viendo que hay gente dispuesta a ayudar, voy a lanzaros una duda que me ha surgido leyendo una practica:

Estoy ahora con listas, segun el enunciado, los objetos de una clase lista concreta tienen que tener un nombre que los identifique. Pues me piden que declaraciones tengo q poner en dicha clase para que cualquier programa pueda modificar/conocer el nombre de la lista, teniendo en cuenta que cualquier dato que se declare en la clase debe de ser privado.

Se que mediante el parametro "friend" haces que otra funcion use la parte privada de tu clase, pero tmb puede modificarla? Aqui creo que la herencia tiene poco sentido, ya que la herencia podria modificar ese nombre desde la clase derivada, pero no lo modificaria en la base no? (perdonar que este tan pesado con la herencia, pero es q deberia de salir, sino es en esta practica en la siguiente, y siempre la tengo en mente)

Creo que no voy muy perdido, de todos modos estas cositas noes q no las sepa x no estudiar, sino q el profesor nos pasa unos cuestionarios previos a la practica sobre cosas nuevas para que investiguemos un poco, y en la practica se explica todo.
Podrías poner el enunciado? No entiendo muy bien qué es lo que preguntas.

Sobre lo de la predeclaración de tipos no se si será mala práctica o no, pero dudo mucho que reduzca el tamaño del binario respecto a usar un #include. El uso de la predeclaración es necesario por ejemplo cuando al usar un #include provocas una dependencia circular.
En el enunciado de la práctica se indica que los objetos de la clase Lista deben tener un nombre que los identifique. Indica qué declaraciones se deben realizar en dicha clase para cumplir este requisito y para que sea posible desde cualquier programa modificar/conocer el nombre de una lista, teniendo en cuenta que cualquier dato que se declare en la clase debe de ser privado.

Aver si puede ser lo que yo digo en el anterior post.

Un saludo!
Mike-Ville escribió:Indica qué declaraciones se deben realizar en dicha clase para cumplir este requisito y para que sea posible desde cualquier programa modificar/conocer el nombre de una lista, teniendo en cuenta que cualquier dato que se declare en la clase debe de ser privado.

Huele a getters y setters.
darix2006 escribió:urosidoki, dices que si usas punteros es mejor usar eso.

Pero mi ejemplo funcionaria sin el include?



Sip :) El include en el .h sobra si vas a usar punteros
Mike-Ville escribió:En el enunciado de la práctica se indica que los objetos de la clase Lista deben tener un nombre que los identifique. Indica qué declaraciones se deben realizar en dicha clase para cumplir este requisito y para que sea posible desde cualquier programa modificar/conocer el nombre de una lista, teniendo en cuenta que cualquier dato que se declare en la clase debe de ser privado.

Aver si puede ser lo que yo digo en el anterior post.

Un saludo!


Por lo que he entendido la clase Lista tiene un atributo nombre, entonces las declaraciones que tiene que hacer son 2 metodos, el metodo getNombre y el metodo setNombre, uno te devuelve lo que contiene el atributo Nombre y el otro le pasas como parametro algo del tipo que tenga Nombre para modificar su valor dentro del objeto creado de la clase Lista

EDIT: el nombre de esos metodos no tiene porque ser asi, simplemente es un convenio elegido (yo uso otro)
Lo de los métodos get/set es más bien cosa de Java, pero a fin de cuentas la idea es la misma...
cracker_ct escribió:Lo de los métodos get/set es más bien cosa de Java

Salvo que no y además tampoco. ¿En qué te basas para decir eso?
Me baso en lo que conozco (que por otro lado puede que sea bastante poco... xD).

Yo toda la programación orientada a objetos que conozco es Java, de C++ sé programar en su subconjunto sin objetos que es C. Digo que más bien es cosa de Java (o eso creo yo, así fue como me lo enseñaron a mí) porque yo he usado ese convenio para los nombres de los métodos.

Pero también digo que la idea a fin de cuentas es la misma, porque la idea es crear un método (o función en C/C++) para obtener el valor de un atributo (get) o establecer el valor de un atributo (set).

Siento si he creado discrepancias, no era mi intención ;)
No hay ningun subforo que hablen de programacion o algo asi?
Podria estar interesante para discutir sobre aspectos del lenguaje
cracker_ct escribió:Me baso en lo que conozco (que por otro lado puede que sea bastante poco... xD).

Yo toda la programación orientada a objetos que conozco es Java, de C++ sé programar en su subconjunto sin objetos que es C. Digo que más bien es cosa de Java (o eso creo yo, así fue como me lo enseñaron a mí) porque yo he usado ese convenio para los nombres de los métodos.

Pero también digo que la idea a fin de cuentas es la misma, porque la idea es crear un método (o función en C/C++) para obtener el valor de un atributo (get) o establecer el valor de un atributo (set).

Siento si he creado discrepancias, no era mi intención ;)

Bueno, pues que sepas que Java deriva de c++, y esas construcciones seguro que aparecieron antes que c++ ;)

Hay un foro de desarrollo, y aunque en teoría no es un foor para aprender a programar las dudas de este tipo de cosas supongo que no estarían de más allí :)
cracker_ct escribió:Me baso en lo que conozco (que por otro lado puede que sea bastante poco... xD).

Yo toda la programación orientada a objetos que conozco es Java, de C++ sé programar en su subconjunto sin objetos que es C. Digo que más bien es cosa de Java (o eso creo yo, así fue como me lo enseñaron a mí) porque yo he usado ese convenio para los nombres de los métodos.

Pero también digo que la idea a fin de cuentas es la misma, porque la idea es crear un método (o función en C/C++) para obtener el valor de un atributo (get) o establecer el valor de un atributo (set).

Siento si he creado discrepancias, no era mi intención ;)


La práctica de los metodos get/set ha existido siempre desde el nacimiento de la POO y la importancia de la encapsulación. Por cierto, que yo sepa el único lenguaje orientado a objetos que no los usa sin pasarse la encapsualización por el forro es C# con sus famosas "propiedades".

Respecto a la práctica: La herencia solo se usa cuando estamos hablando de una especialización, por ejemplo, tenemos una clase pajaro que implementa métodos como volar() y morir() (que son cosas comunes para todos los pajaros), de la que heredan una clase loro que implementa hablar() y una clase periquito que implementa piar(). Despues, al crear una instancia de loro podras llamar a hablar(), a morir() y a volar() y si la instancia es de periquito podrías llamar a piar(), morir() y a volar().

No intentes usar herencia en ningún caso que no sea algo así, en la que varias clases son una especialización de otra.
kbks escribió:La práctica de los metodos get/set ha existido siempre desde el nacimiento de la POO y la importancia de la encapsulación. Por cierto, que yo sepa el único lenguaje orientado a objetos que no los usa sin pasarse la encapsualización por el forro es C# con sus famosas "propiedades".

Hay más lenguajes que usan propiedades (Ruby accessors)

Además, las propiedades de C# en realidad es un caramelo del compilador, ya que en realidad el proceso de compilación los traduce a getters y setters.
int MiPropiedad {get{...}; set{..}} en realidad se traduce en dos métodos:
int get_MiPropiedad();
void set_MiPropiedad(int value);


No intentes usar herencia en ningún caso que no sea algo así, en la que varias clases son una especialización de otra.

Hay casos en los que hacer eso es más que aceptable, aunque no sea lo mejor en teoría como bien dices.
27 respuestas