Форум программистов, компьютерный форум CyberForum.ru

Указатели - C++

Восстановить пароль Регистрация
 
 
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 11:06     Указатели #1
Всем здрасьте !
Тут на днях я прочитал про указатели в одной книге , и мало что о них понял.
Не могил бы вы мне рассказать , что это такое и что из себя представляют указатели.
Ну и пример простенький , заранее благодарен !
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
abit
 Аватар для abit
260 / 259 / 33
Регистрация: 03.02.2013
Сообщений: 709
05.02.2013, 11:48     Указатели #2
Цитата Сообщение от BeginerMan Посмотреть сообщение
Всем здрасьте !
Тут на днях я прочитал про указатели в одной книге , и мало что о них понял.
Не могил бы вы мне рассказать , что это такое и что из себя представляют указатели.
Ну и пример простенький , заранее благодарен !
почитайте в другой книге)))
по сути это адрес на данные/код (либо никуда не ведущий - nil)
тема не на две строчки

Не по теме:

вопрос из разряда - я тут нашёл руль на свалке, не подскажите как собрать автомобиль

fuzzytoozy
8 / 8 / 1
Регистрация: 23.11.2012
Сообщений: 94
05.02.2013, 12:34     Указатели #3
Указатели представляют собой адресные переменные. То есть они содержат адрес объекта/переменной в памяти. Например переменная int omg; cout << &omg; выведет её адрес. Определив указатель на переменную int следующим образом: int *ptr; можем присвоить ему адрес переменной omg, ptr = &omg; так же мы можем присвоить указателю адрес переменной используя операцию расшифровки, она тоже выглядит как символ *.
Важно не путать с символом * в определении указателя, здесь мы используем его, чтобы создать указатель. Опять же пример с переменной int omg;. Присваиваем адрес переменной omg указателю ptr. *ptr = omg;. Операция расшифровки, заставляет указатель выдать нам собственно объект на который он указывает, то есть переменную типа int (так как мы определили указатель на переменную int ).
Указатель может быть на любой тип данных, включая пользовательские, так же может указывать на массив. Существует такое понятие, как константный указатель. Выглядит это примерно так:
C++
1
const int *ptr;
в этом случае значение указателя ( адрес ) не может быть изменен, короче говоря, место в памяти, за определенным номером, занимаемое переменной типа int ( так как наш указатель, есть указатель на тип int ) изменено быть не может. Существует так же такое понятие, как указатель на константу и выглядит это так:
C++
1
int const *ptr;
в данном случае содержимое указателя изменено быть не может( то на что указывает указатель, в данном случае переменная типа int ), однако оно может быть помещено в другую область памяти, то есть может быть изменено значение указателя.

Существует так же такое понятие, как указатель на указатель, например:
C++
1
char **ptr;
таким образом определяем указатель на указатель типа char;
Можно, например, определить массив указателей на указатели:
C++
1
char** ptr[10];
имеем 10 указателей на char и таким образом можем внести в один массив 10 строк:
C++
1
*ptr[0] = " string 1 "; *ptr[1] = " string 2 ";
ну и собственно так далее. Такой синтаксис возможен, так как массив, обычный массив типа char (например), есть указатель на его первый элемент, то есть указатель, на область памяти, начиная с которой можно считывать данные, находящиеся в массиве.

Для вызова функции через указатель можно применять 2 операции. Допустим у нас есть некий класс ZOMG, и мы определили указатель на объект этого класса:
C++
1
2
ZOMG o1; 
ZOMG *ptr = &o1;
Теперь, чтобы вызвать любую функцию для объекта o1, на который указывает наш указатель ptr мы можем сделать так:
C++
1
2
3
*ptr.func( );
// или так:
ptr->func( );
Фактически, операция -> разыменовывает указатель и вызывает функцию, поэтому нам не нужно применять операцию * разыменования.

Для указателей существует две очень полезные операции: new и delete. Они позволяют динамически выделить память под объект и освободить её. Например:
C++
1
char* ptr = new char[10];
Такая команда выделяет память для массива типа char содержащего 10 символов, не больше, не меньше.
Так же мы можем выделить память для любых пользовательских данных, для объекта класса ZOMG, например:
C++
1
2
ZOMG o1;
ZOMG *ptr = new o1;
этой командой, мы выделяем памяти ровно столько, сколько достаточно для хранения одного экземпляра объекта класса ZOMG.
Чтобы освободить память, нам достаточно написать:
C++
1
delete ptr;
При работе с указателями следует быть осторожными, так как, если указатель не инициализировать какими - либо данными, он будет содержать в себе случайную область памяти и работа с таким указателем может привести к серьезным ошибкам в ОС.
Надеюсь, что то что я вам поведал поможет хоть как нибудь =)
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 13:05  [ТС]     Указатели #4
Уф , стало более понятно , но вот у меня вопросик
Вот кодишко:
C++
1
2
3
4
    Dragon* dragons[3];
    dragons[0] = new RedDragon(1);
    dragons[1] = new BlueDragon(2);
    dragons[2] = new BlackDragon(3);
Почему он у меня ругается на знак "=" в dragons[0] и в dragons[1] , а в dragons[2] он ничего не говорит , почему так??
Пишет вот такую ошибку : "Значение типа "RedDragon*" нельзя присвоить сущности типа "Dragon*"".
Если надо могу скинуть и другие файлы типо Dragon.cpp , RedDragon.cpp и т.д. Но там ошибок нет вроде.
Помогите , зарание спасибо ^^
fuzzytoozy
8 / 8 / 1
Регистрация: 23.11.2012
Сообщений: 94
05.02.2013, 13:16     Указатели #5
если RedDragon и так далее, не является производным классом от Dragon, то данная операция невозможна.

Добавлено через 6 минут
попробуйте исправить в исходниках, если хотите так поступать и оно вам точно нужно. И если я правильно понял, что BlueDragon, RedDragon и BlackDragon это классы, то в объявлениях классов нужно написать:
C++
1
2
3
4
class RedDragon : public Dragon
{
 // данные класса
};
и так далее. В этом случае, приведенные вами выше операции будут работать.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
05.02.2013, 13:19     Указатели #6
Первое предположение: RedDragon и BlueDragon не являются наследниками Dragon, а BlackDragon является.
Вообще, вам бы сначала с указателями разобраться, а не в полиморфизм лезть.
fuzzytoozy
8 / 8 / 1
Регистрация: 23.11.2012
Сообщений: 94
05.02.2013, 13:21     Указатели #7
я ведь тоже самое сказал =)
silent_1991
05.02.2013, 13:34
  #8

Не по теме:

Цитата Сообщение от fuzzytoozy Посмотреть сообщение
я ведь тоже самое сказал =)
А это мне просто надо на монитор приклеить надпись "почаще обновляй страницы" Не видел вашего сообщения, пока писал своё.

BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 13:34  [ТС]     Указатели #9
Так , С указателями я разберусь позже , для начала надо спасти "моё переделанное творение из книги"
Вот класс Dragon:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Dragon
{
private:
    int speed;
    string name;
    int HP;
    int armor;
    int treasure;
    int Damage;
    int size;
protected:
    Dragon(int theSize);
    int getArmor() {return armor;}
    int& getHP() {return HP;}
    int getDamage() {return Damage;}
    int getSize() {return size;}
    virtual int Attack(int targetArmor , int specialDamage);
public:
    virtual int attack(int targetArmor) = 0;
    virtual void defend(int damage) = 0;
    int getTreasure() {return treasure;}
    virtual string getName() {return name;}
    int getSpeed() {return speed;}
    bool isAlive() {return HP > 0;}
};
Вот класс RedDragon:
C++
1
2
3
4
5
6
7
8
9
10
class RedDragon : public Dragon
{
private:
    int FireDamage;
public:
    RedDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Красный дракон";}
};
Вот класс BlueDragon
C++
1
2
3
4
5
6
7
8
9
10
class BlueDragon : public Dragon
{
private:
     int IceDamage;
public:
    BlueDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Синий дракон";}
};
Вот класс BlackDragon:
C++
1
2
3
4
5
6
7
8
9
10
class BlackDragon : public Dragon
{
private:
    int PoisonDamage;
public:
    BlackDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Чёрный дракон";}
};
Каждый класс в своём файле . типо RedDragon.cpp
И в файлах .cpp где произвдные классы я прописал #include "Dragon.cpp"
Ну вот Почему то с BlackDragon нет проблем , а с другими есть .
Если вы мне поможете , я буду сильно благодарен !
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
05.02.2013, 13:39     Указатели #10
Цитата Сообщение от BeginerMan Посмотреть сообщение
#include "Dragon.cpp"
Зачем О___о. Подключать надо заголовочные файлы, но никак не файлы реализации.
Выложите все файлы, будем посмотреть, пока что ошибок вроде не вижу...
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 13:50  [ТС]     Указатели #11
Главный файлик DragonLord.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include "Dragon.cpp"
#include "RedDragon.cpp"
#include "BlueDragon.cpp"
#include "BlackDragon.cpp"
using namespace std;
 
int menuChoise();
 
int main(void)
{
    srand(time(0));
    Dragon* dragons[3];
    int hp = 15;
    int armor = 2;
    int tempArmor;
    int tempAttack;
    dragons[0] = new RedDragon(rand()%4+1);
    dragons[1] = new BlueDragon(rand()%4+1);
    dragons[2] = new BlackDragon(rand()%4+1);
    Dragon* d = dragons[rand()%3];
    cout << "Здарова"<<endl<<"Её похитил "<<d->getName()<<"."<<endl;
    cout << "Твоя сила" << hp << endl;
    while(d->isAlive() && hp > 0)
    {
        int Choise = menuChoise();
        if (Choise == 3) goto RUN;
        else if (Choise == 1)
        {
            tempAttack = rand()%16+5;
            tempArmor = armor;
        }
        else
        {
            tempAttack = rand()%11;
            tempArmor = armor + 4;
        }
        hp -= d->attack(armor);
        d->defend(rand()%16-5);
        cout << "Ты наносишь мощный удар"<< tempAttack << "damage.\n";
        cout << "Твоя сила" << hp;
    }
    if(d->isAlive())
        cout << "\nТы побеждён !";
    else
        cout << "\nТы убил Дракона !";
    return 0;
RUN:
    cout << "\nТы убежал";
    return 0;
}
int menuChoise()
{
    int Choise;
        do
        {
            cout << endl
                << "[1]Атаковать\n"
                << "[2]Обороняться\n"
                << "[3]Бежать\n";
            cin >> Choise;
 
        }while (Choise < 1 && Choise >3);
        return 0;
}
Второй файлик с базовым классом Dragon.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
using namespace std;
 
#define MAX(a,b) a>b? a:b
 
class Dragon
{
private:
    int speed;
    string name;
    int HP;
    int armor;
    int treasure;
    int Damage;
    int size;
protected:
    Dragon(int theSize);
    int getArmor() {return armor;}
    int& getHP() {return HP;}
    int getDamage() {return Damage;}
    int getSize() {return size;}
    virtual int Attack(int targetArmor , int specialDamage);
public:
    virtual int attack(int targetArmor) = 0;
    virtual void defend(int damage) = 0;
    int getTreasure() {return treasure;}
    virtual string getName() {return name;}
    int getSpeed() {return speed;}
    bool isAlive() {return HP > 0;}
};
 
Dragon::Dragon(int theSize) : size(theSize)
{
    if(size < 1 || size > 4)
        size = 3;
    Damage = 2 * size;
    speed = 3 * size;
    HP = 4 * size;
    armor = size;
    treasure = 1000 * size;
    srand(time(0));
}
 
int Dragon::Attack(int targetArmor , int specialDamage)
{
    int useSpecial = rand() %2;
    int Damage;
    if(useSpecial)
        Damage = specialDamage;
    else Damage = getDamage();
    return MAX(Damage - targetArmor , 0);
}
Третий файл с производным классом RedDragon.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include "Dragon.cpp"
using namespace std;
 
class RedDragon : public Dragon
{
private:
    int FireDamage;
public:
    RedDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Красный дракон";}
};
 
RedDragon::RedDragon(int theSize) : Dragon(theSize)
{
    FireDamage = 4 * getSize();
}
 
int RedDragon::attack(int targetArmor)
{
    return Dragon::Attack(targetArmor , FireDamage);
}
 
void RedDragon::defend(int Damage)
{
    getHP() -= (Damage - getArmor()) / 3;;
}
Четвёртый файл с производным классом BlueDragon.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include "Dragon.cpp"
using namespace std;
 
class BlueDragon : public Dragon
{
private:
     int IceDamage;
public:
    BlueDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Синий дракон";}
};
 
BlueDragon::BlueDragon(int theSize) : Dragon(theSize)
{
    IceDamage = 3 * getSize();
}
 
int BlueDragon::attack(int targetArmor)
{
    return Dragon::Attack(targetArmor , IceDamage);
}
 
void BlueDragon::defend(int Damage)
{
    getHP() -= (Damage - getArmor()) / 2;
}
Пятый файл с производным классом BlackDragon.cpp:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "stdafx.h"
#include <iostream>
#include <string>
#include <ctime>
#include <cstdlib>
#include "Dragon.cpp"
using namespace std;
 
class BlackDragon : public Dragon
{
private:
    int PoisonDamage;
public:
    BlackDragon(int theSize);
    int attack (int targetArmor);
    void defend (int Damage);
    string getName () {return "Чёрный дракон";}
};
 
BlackDragon::BlackDragon(int theSize) : Dragon(theSize)
{
    PoisonDamage = getSize();
}
 
int BlackDragon::attack(int targetArmor)
{
    return Dragon::Attack(targetArmor , PoisonDamage);
}
 
void BlackDragon::defend(int Damage)
{
    getHP() -= Damage - getArmor();
}
Deimon
 Аватар для Deimon
34 / 34 / 2
Регистрация: 29.08.2009
Сообщений: 178
05.02.2013, 14:31     Указатели #12
Цитата Сообщение от BeginerMan Посмотреть сообщение
Почему он у меня ругается на знак "=" в dragons[0] и в dragons[1] , а в dragons[2] он ничего не говорит , почему так??
Пишет вот такую ошибку : "Значение типа "RedDragon*" нельзя присвоить сущности типа "Dragon*"".
Если надо могу скинуть и другие файлы типо Dragon.cpp , RedDragon.cpp и т.д. Но там ошибок нет вроде.
Цитата Сообщение от BeginerMan Посмотреть сообщение
C++
1
2
3
4
Dragon* dragons[3];
* * dragons[0] = new RedDragon(1);
* * dragons[1] = new BlueDragon(2);
* * dragons[2] = new BlackDragon(3);
Попытки ради, можете поменять RedDragon и BlackDragon местами, и будут ли изменения в содержании ошибок?!

Не по теме:

Удобнее копировать лог ошибок прямо из компилятора.


Это единственная ошибки, которые выдал компилятор?

А у вас h файлы есть? или вы создавали cpp файлы и писали все в них?
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 14:36  [ТС]     Указатели #13
Только .cpp файл , по книге которой я писал , только cpp файлы
Книга Хенкеманса.
Да хоть как менял пробовал , верно было только с BlackDragon
Deimon
 Аватар для Deimon
34 / 34 / 2
Регистрация: 29.08.2009
Сообщений: 178
05.02.2013, 14:41     Указатели #14
BeginerMan, Вы ведь могли кинуть архивом весь проект, это очень бы ускорело понимание проблемы)

Цитата Сообщение от BeginerMan Посмотреть сообщение
Только .cpp файл , по книге которой я писал , только cpp файлы
предпологаю, проблема не в отсутствии .h файлов
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 14:46  [ТС]     Указатели #15
Ну давайте архив скину , какие ещё надо запихнуть файлы кроме .cpp ??Что бы проект сохранился как бы.
Deimon
 Аватар для Deimon
34 / 34 / 2
Регистрация: 29.08.2009
Сообщений: 178
05.02.2013, 14:54     Указатели #16
BeginerMan, у вас же есть папка, в которой сохранен проект. Киньте всю папку. Можно конечно удалить файлы котоыре Вы создавали ранее и не используете сейчас, скрытую папку history если таковая имеется. Помимо срр, по идеи еще должен быть сам файл .project.

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

Но у меня такое подозрение, что Вы пишите в Визуал, и мой Билдер это не откроет =(
I.M.
 Аватар для I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
05.02.2013, 14:54     Указатели #17
BeginerMan, где include guard'ы? неужели автор книги тоже подключает срр файлы?
Согласен, что язык или что-либо изучать гораздо интереснее в игровой форме, но тем не менее, я бы посоветовал хотя бы параллельно читать обычную книжку по С++.
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
05.02.2013, 14:56     Указатели #18
Цитата Сообщение от I.M. Посмотреть сообщение
неужели автор книги тоже подключает срр файлы?
Если так - сжечь книгу (и желательно автора).
BeginerMan
 Аватар для BeginerMan
49 / 48 / 5
Регистрация: 17.11.2012
Сообщений: 418
05.02.2013, 17:30  [ТС]     Указатели #19
Да да у меня Визуал , извените должен уходить D;
Кто поможет спасибо большое , я отлучаюсь

Добавлено через 2 часа 33 минуты
Так ладно , можете закрывать тему или как у вас тут , сам пойду всё перечитывать и переделовать , всем спасибо за помощь
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.02.2013, 17:40     Указатели
Еще ссылки по теме:

C++ Написать программу сортировки через указатели на указатели
Указатели и массивы. Указатели и функции C++
Указатели на массивы. Указатели и функции C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
silent_1991
Эксперт C++
4938 / 3014 / 149
Регистрация: 11.11.2009
Сообщений: 7,024
Завершенные тесты: 1
05.02.2013, 17:40     Указатели #20
BeginerMan, какие мы нежные... Объединил ваш код в один файл, всё компилируется. Вот:
http://liveworkspace.org/code/21CrG$0
Yandex
Объявления
05.02.2013, 17:40     Указатели
Ответ Создать тему
Опции темы

Текущее время: 17:21. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru