Указатель будет случайным образом выводить свой адрес вместо указанного значения, C ++ - PullRequest
0 голосов
/ 31 марта 2012

Итак, у меня есть проблема, когда вывод выводит адрес моего указателя, я понятия не имею, почему это происходит, потому что указатели вообще не модифицируются

Вот код:

using namespace std;

class AndroideAbstracto {
protected:
    int *vida;
    int *fuerza;
    int *velocidad;
public:

    void setvalores(int vi, int fu, int ve) {
        velocidad = &ve;
        vida = &vi;
        fuerza = &fu;

    };
    virtual void imprimir(void) = 0;
};

class Androide : public AndroideAbstracto {
public:

    void imprimir() {
        std::cout << "Caracteristicas del androide:" << endl;
        cout << "Velocidad = " << *velocidad << endl;
        cout << "Vida = " << *vida << endl;
        cout << "Fuerza = " << *fuerza << endl;

    };

};

class Decorator : public AndroideAbstracto {
protected:
    AndroideAbstracto *AndroideDec;
public:

    Decorator(AndroideAbstracto* android_abs) {
        AndroideDec = android_abs;
    }
    virtual void imprimir(void) = 0;
};

class Androide_Con_Habi : public Decorator {
protected:
    string habilidad;
public:

    Androide_Con_Habi(AndroideAbstracto* android_abs, string habi) : Decorator(android_abs) {
        habilidad = habi;
    }

    virtual void imprimir() {
        AndroideDec->imprimir();
        cout << "La habilidad especial del androide es: " << habilidad << endl;
    }
};

class Androide_Elegido : public Decorator {
protected:
    bool elegido;
public:

    Androide_Elegido(AndroideAbstracto *android_abs, bool es) : Decorator(android_abs) {
        elegido = es;
    }

    virtual void imprimir() {
        if (elegido) {
            //            *vida =(*vida) * 2;  //Im quite new to C++ so im not really
            //            *fuerza *=2;         //sure how should I multiply these pointers
            //            *velocidad *=2;
            //            AndroideDec->setvalores(vida*2,fuerza*2,velocidad*2);
            AndroideDec->imprimir();
            cout << "Este androide es uno de los elegidos";
        }
    }
};

int main(int argc, char *argv[]) {

    Androide *andro = new Androide();
    andro->setvalores(600, 700, 300);
    andro->imprimir();
    Androide_Con_Habi *andro_con_habi = new Androide_Con_Habi(andro, "Volar");
    andro_con_habi->imprimir();

    Androide_Elegido *superpoderoso = new Androide_Elegido(andro, true);
    superpoderoso->imprimir();

    delete superpoderoso;
    delete andro;
    delete andro_con_habi;
    return 0;
}

Я понятия не имею, почему, но это печатает:

Caracteristicas del androide:
Velocidad = 300
Vida = 600
Fuerza = 700

Caracteristicas del androide:
Velocidad = 300
Vida = 152436744
Fuerza = -1074718788
La habilidad especial del androide es: Volar


Caracteristicas del androide:
Velocidad = 300
Vida = 152436744
Fuerza = 1
Este androide es uno de los elegidos 

Ответы [ 2 ]

3 голосов
/ 31 марта 2012
void setvalores(int vi, int fu, int ve) {
    velocidad = &ve;
    vida = &vi;
    fuerza = &fu;

};

Указатели на vi, fu и ve становятся недействительными, когда функция возвращается.Вы не видите распечатанные адреса, а просто мусор.

Хотя весь ваш дизайн не использует и не должен использовать указатели.

0 голосов
/ 31 марта 2012

То, что вы видите, это адреса формальных параметров вашей функции. По сути бессмысленные значения, которые бесполезны и по сути будут указателями на случайную позицию в вашем стеке - где бы ни находился стек, когда вы вызывали конструктор. В принципе, вам никогда не будут интересны эти значения, если вы не попытаетесь узнать больше о том, как работает ваш компьютер и компилятор.

Очень важно понимать, что делают указатели и когда они уместны, и каковы их последствия.

В этом случае не рекомендуется использовать указатели, потому что:

  • Вы пытаетесь хранить данные внутри своего класса, и тип, который вы храните:
    • В любом случае тот же размер, что и указатель (int)
    • Нет причин хранить память за пределами вашего класса (в любом случае, не показано)
    • даже если вам нужно, ссылки будут менее подвержены ошибкам (int & вместо int *)
  • Кроме того, вы используете кучу для создания экземпляра вашего класса, когда стек будет работать нормально.

Я подозреваю, что это то, что вы намеревались:

class AndroideAbstracto {
protected:
    int vida;
    int fuerza;
    int velocidad;
public:

    void setvalores(int vi, int fu, int ve) {
        velocidad = ve;
        vida = vi;
        fuerza = fu;

    };
    virtual void imprimir(void) = 0;
};

class Androide : public AndroideAbstracto {
public:
    void imprimir() {
        std::cout << "Caracteristicas del androide:" << endl;
        cout << "Velocidad = " << velocidad << endl;
        cout << "Vida = " << vida << endl;
        cout << "Fuerza = " << fuerza << endl;
    };
};

Обратите внимание на отсутствие * как в типах членов класса, так и при распечатке значений.

Одно не очень удачное, но синтаксически правильное использование указателей здесь было бы для запроса нескольких значений в классе одним вызовом (помещенным в любой класс):

void getvalores(int *vi, int *fu, int *ve) {
    if (vi)
        *vi = vida;
    if (fu)
        *fu = fuerza;
    if (ve)
        *ve = velocidad;
}

называется так, например:

int vida, velocidad;
andro->getvalores(&vida, NULL, &velocidad);

cout << "Velocidad = " << velocidad << endl;
cout << "Vida = " << vida << endl;

Здесь мы передали адрес переменных стека vida и velocidad как указатели и передали NULL, где мы могли бы передать дополнительный адрес, потому что нам не нужно значение fuerza. Затем мы присваиваем памяти, на которую указывают переданные указатели, если они не равны NULL, и когда функция возвращает, переменные стека имеют значения из класса.

Конечно, вы не должны этого делать - вы просто должны предоставить доступ к значениям другим способом, либо напрямую, либо сделав их общедоступными, либо добавив функции, которые просто возвращают их.

public:
    int Vida() {
        return vida;
    }

Тогда вы можете просто сделать:

cout << "Vida = " << andro->Vida() << endl;

И, конечно, если нет причины использовать кучу для создания экземпляра Androide, вам следует просто использовать стековую память вместо кучи.

Androide andro;

вместо

Androide *andro = new Androide();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...