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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
eoLithic
0 / 0 / 0
Регистрация: 05.01.2013
Сообщений: 32
#1

Динамически создать массив - C++

31.01.2013, 05:22. Просмотров 548. Ответов 8
Метки нет (Все метки)

Все чуть посложнее, чем кажется.
Goat, Wolf, Cowboy - производные классы от Animal. Динамически создаем массивы из Goat и Wolf. Cowboy - только один. Затем, поскольку у них у всех есть виртуальные функции, которые мне надо использовать, я создаю массив указателей на тип Animal.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
cout<<"How many goats? ";  // Сколько коз в стаде
cin>>numberOfGoats;
Goat *ptrGoats = new Goat[ numberOfGoats ];
 
cout<<"How many wolves: "; // Сколько волков должны напасть
cin>>numberOfWolves;
Wolf *ptrWolves = new Wolf[ numberOfWolves ]; 
 
const int totalAnimals = numberOfWolves + numberOfGoats + 1; // Общее количество животных ( включая пастуха )
 
Animal *ptrAnimals[ totalAnimals ] = ptrGoats; // Вот тут и встает проблема. Если и тут динамически выделить память,
ptrAnimals[ totalAnimals - numberOfWolves ] = ptrWolves;  // то встает другая проблема. О ней ниже.
ptrAnimals[ totalAnimals - 1 ] = &cowboy;
Animal *ptrAnimals[ totalAnimals ] = ptrGoats; можно сделать типа: Animal *ptr = new Animal[ totalAnimals ]; , но в этом случае не получается заставить ptrAnimals указывать на ptrGoats, и на ptrWolves и на Cowboy.
А если этого не сделать, то меня ждет морока в коде и дописывание кучи циклов для каждого производного класса, когда можно все запихнуть в один массив и вызывать их виртуальные функции в одном цикле.

Есть идеи решения этой проблемы?

Добавлено через 4 минуты
И раз пошла такая пьянка, то еще один вопрос:
Есть базовый класс, есть производный класс. В базовом классе есть public функция "Кушать". Она ведь наследуется производному классу, не так ли? Ее не надо объявлять в интерфейсе производного класса или надо?
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
31.01.2013, 05:22
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Динамически создать массив (C++):

Динамически создать и удалить vector - C++
Доброго времени суток у меня имеется двумерный vector объектов класса,добавляю туда элементы создавая одномерный veсtor и push_back к...

Как создать DLL в VS2010 C++ Динамически подключаемую? - C++
Подскажите кто знает пробовал тут сам зделать не получилось

Динамически расширяемый массив - C++
Не получается добавить элементы в начало массива, прошу помочь/подсказать #include &lt;iostream&gt; using namespace std; class myVector {...

динамически создать/удалить объекты класса (правильно сделал?) - C++
создал класс: myclass { } завел вектор, в котором будут храниться указатели на объекты данного класса: vector &lt;myclass*&gt; ob; ...

одномерный динамически массив(экзамен) - C++
В целочесленной последовательности есть нулевые элементы. Создать массив из номеров этих элементов. сделать через файлы и функции....

Как задать динамически массив? - C++
Как задать динамически массив? Какой заголовчный файл необходим? Int *B=new A n=100 Заработает ли?

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
lemegeton
2924 / 1353 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
31.01.2013, 08:51 #2
Цитата Сообщение от eoLithic Посмотреть сообщение
Есть базовый класс, есть производный класс. В базовом классе есть public функция "Кушать". Она ведь наследуется производному классу, не так ли? Ее не надо объявлять в интерфейсе производного класса или надо?
Наследуется. Не надо. Но, если вы захотите её специфицировать и вызвать из базового класса, придется сделать её виртуальной.

Цитата Сообщение от eoLithic Посмотреть сообщение
Есть идеи решения этой проблемы?
Что вам мешает скопировать адреса объектов в новый массив?

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
#include <cstdlib>
#include <ctime>
#include <iostream>
 
class Animal {
 public:
  virtual void eat() = 0; // абстрактная виртуальная функция
};
 
class Wolf : public Animal {
 public:
  virtual void eat() {
    std::cout << "wolf eats" << std::endl;
  }
};
 
class Goat : public Animal {
 public:
  virtual void eat() {
    std::cout << "goat eats" << std::endl;
  }
};
 
// этот ковбой настоящее животное
class Cowboy : public Animal {
 public:
  virtual void eat() {
    std::cout << "cowboy eats" << std::endl;
  }
};
 
int main(int argc, char **argv) {
  srand(time(0));
 
  int numberOfGoats = 5 + rand() % 10;
  Goat *goats = new Goat[numberOfGoats];
 
  int numberOfWolves = 5 + rand() % 10;
  Wolf *wolves = new Wolf[numberOfWolves];
 
  Cowboy *cowboy = new Cowboy();
 
  int numberOfAnimals = numberOfGoats + numberOfWolves + 1;
  // указатель (массив) указателей на животных
  Animal **animals = new Animal*[numberOfAnimals];
  
  int j = 0;
  // кладем в массив _адреса_ животных
  for (int i = 0; i < numberOfGoats; ++i) animals[j++] = goats + i; // aka &(goats[i])
  for (int i = 0; i < numberOfWolves; ++i) animals[j++] = wolves + i; // aka &(wolves[i])
  animals[j++] = cowboy;
 
  // ну и можно пользоваться
  for (int i = 0; i < numberOfAnimals; ++i) {
    animals[i]->eat();
  }
  
  delete [] goats;
  delete [] wolves;
  delete cowboy;
  std::cin.get();
  return 0;
}
1
eoLithic
0 / 0 / 0
Регистрация: 05.01.2013
Сообщений: 32
31.01.2013, 12:26  [ТС] #3
Допустим
C++
1
2
3
4
5
6
7
8
9
10
11
12
class Animal
{
public:
void setName( string );
string getName() const;
 
private:
string name;
};
 
string Animal::getName()
{   return name;  }
C++
1
2
3
4
5
6
7
class Human : public Animal
{
//Для того, чтобы объекты Human могли пользоваться 
//функцией getName() , реализация которой не отличается 
//от реализации в базовом классе, нужно ли мне объявлять
//getName() в интерфейсе Human.h ?
}
Добавлено через 2 часа 5 минут
Помогите, пожалуйста, еще кое с чем.
Допустим, функцию int AnotherClass::randomPoint() вызывают только объекты SomeClass. Я хочу, чтобы функция randomPoint() проверяла количество очков у объекта SomeClass, вызвавшего ее, и в определенном случае возвращала 100 очков. Хотел использовать указатель this, но он вернет мне адреса объекта object из SomeClass, не так ли?
Как сделать так, чтобы функция randomPoint() проверяла значение points объекта SomeClass, который ее вызвал?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
class AnotherClass
{
public:
int randomPoint();
private:
int point;
};
 
int AnotherClass::randomPoint()
{
point = rand() % 10;
return point;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SomeClass
{
public:
void addPoints();
 
private:
int points;
AnotherClass object;
};
 
void SomeClass::addPoints()
{
points += object.randomPoint;
}
0
ya_noob
_
201 / 145 / 9
Регистрация: 08.10.2011
Сообщений: 432
31.01.2013, 13:57 #4
Цитата Сообщение от eoLithic Посмотреть сообщение
Хотел использовать указатель this, но он вернет мне адреса объекта object из SomeClass, не так ли?
Так. Добавь метод get для points в классе SomeClass и в функции randomPoints() вызывай что-то типа "ptr->getPoints();", где ptr == this
0
lemegeton
2924 / 1353 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
31.01.2013, 14:09 #5
Цитата Сообщение от eoLithic Посмотреть сообщение
//Для того, чтобы объекты Human могли пользоваться
//функцией getName() , реализация которой не отличается
//от реализации в базовом классе, нужно ли мне объявлять
//getName() в интерфейсе Human.h ?
Нет, не нужно.

Цитата Сообщение от eoLithic Посмотреть сообщение
Как сделать так, чтобы функция randomPoint() проверяла значение points объекта SomeClass, который ее вызвал?
С точки зрения архитектуры и универсальности лучше эту логику перекроить так, чтобы только один класс управлял points'ами.
Приведите более конкретный пример, где это необходимо. С SomeClass и AnotherClass я что-то путаюсь и не могу придумать пример.
1
eoLithic
0 / 0 / 0
Регистрация: 05.01.2013
Сообщений: 32
01.02.2013, 00:05  [ТС] #6
lemegeton,
Пример:
Объект класса Gambler вызывает функцию getCard(). В зависимости от того сколько очков у игрока, функция выдает ему определенное количество очков. Но функция getCard() в своем теле вызывает функцию giveACard() класса KolodaKart и giveACard() должна узнавать сколько очков у объекта типа Gamber, который вызвал ее. В этом и вся проблема.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class KolodaKart
{
public:
void rastasovatKolodu();
int giveACard();
 
private:
KARTA karta[52]; // KARTA - это структура
};
 
int KolodaKart::giveACard()
{   
if ( getPoints > 20 ) // Тут встает проблема: как узнать какой объект Gambler вызвал эту функцию?
return 0;    // Не знаю как это сделать.
else
return 10;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
class Gambler
public:
void getCard() // тянем карту
int getPoints() // узнать количество очков у объекта
 
private:
static KolodaKart koloda;
int points;
};
 
void Gambler::getCard()
{  points += koloda.giveACard(); }
0
MrGluck
Модератор
Эксперт CЭксперт С++
7239 / 4407 / 642
Регистрация: 29.11.2010
Сообщений: 11,927
01.02.2013, 02:02 #7
Цитата Сообщение от eoLithic Посмотреть сообщение
должна узнавать сколько очков у объекта типа Gamber, который вызвал ее.
что то вы путаетесь в показаниях. Как методы одного класса могут быть вызваны объектом другого класса без создания объекта первого? А если объект есть - то предоставьте интерфейс в виде get методов.
0
lemegeton
2924 / 1353 / 135
Регистрация: 29.11.2010
Сообщений: 2,725
01.02.2013, 09:36 #8
Цитата Сообщение от eoLithic Посмотреть сообщение
Объект класса Gambler вызывает функцию getCard(). В зависимости от того сколько очков у игрока, функция выдает ему определенное количество очков. Но функция getCard() в своем теле вызывает функцию giveACard() класса KolodaKart и giveACard() должна узнавать сколько очков у объекта типа Gamber, который вызвал ее. В этом и вся проблема.
Это проблема в архитектуре. Класс отвечает за слишком многое, потому и возникают такие дилеммы. Старайтесь, чтобы класс отвечал за как можно более узкую область и при этом был как можно более универсальным.

Пример на коленке:
Три (относительно) универсальных класса для игры в очко.
Card -- карта, знает название ранков и мастей (rank & suit)
Deck -- колода, содержит карты, умеет выдавать случайную карту (drow)
Hand -- "рука" игрока, держит карты, умеет уже считать очки (value).
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include <cstdlib>
#include <ctime>
#include <string>
#include <iomanip>
#include <iostream>
#include <set>
#include <vector>
#include <stdexcept>
#include <algorithm>
 
class Card {
 public:
  static const std::string RANKS[];
  static const std::string SUITS[];
  static const int NUMBER_OF_CARDS_PER_SUIT = 15;
  Card(int id) : id(id) {}
  Card(int rank, int suit) : id(suit * NUMBER_OF_CARDS_PER_SUIT + rank) {}
  int getId() const { return id; }
  int getRankId() const { return id % NUMBER_OF_CARDS_PER_SUIT; }
  int getSuitId() const { return id / NUMBER_OF_CARDS_PER_SUIT; }
  const std::string &getRankName() const { return RANKS[getRankId()]; }
  const std::string &getSuitName() const { return SUITS[getSuitId()]; }
 private:
  int id;
};
 
const std::string Card::RANKS[] = {"zero", "one",
  "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten",
  "jack", "queen", "king", "ace"};
const std::string Card::SUITS[] = {"hearts", "diamonds", "clubs", "spades",
  "joker"};
 
std::ostream &operator<<(std::ostream &stream, const Card &card) {
  if (card.getSuitId() < 4) {
    stream << card.getRankName() << " of " << card.getSuitName();
  } else {
    stream << card.getSuitName();
  }
  return stream;
}
 
// Г*Г*äî äëÿ Г¬Г*îæåñòâГ*
bool operator<(const Card &a, const Card &b) {
  if (a.getRankId() == b.getRankId())
    return a.getSuitId() < b.getSuitId();
  return a.getRankId() < b.getRankId();
}
 
class Deck {
 public:
  Deck() : cards() {}
  Card drow() {
    if (cards.empty()) {
      throw std::underflow_error("no cards in deck");
    }
    std::set<Card>::iterator randomCardIterator = cards.begin();
    std::advance(randomCardIterator, rand() % cards.size());
    Card randomCard = *randomCardIterator;
    cards.erase(randomCardIterator);
    return randomCard;
  }
  void reset(int startRankId, int endRankId = Card::NUMBER_OF_CARDS_PER_SUIT,
    int numberOfJokers = 0) {
    cards.clear();
    for (int i = 0; i < 4; ++i) {
      for (int j = startRankId; j < endRankId; ++j) {
        cards.insert(Card(j, i));
      }
    }
    for (int i = 0; i < numberOfJokers; ++i) {
      cards.insert(Card(i, 4));
    }
  }
  bool isEmpty() const {
    return cards.empty();
  }
  int getSize() const {
    return cards.size();
  }
  friend std::ostream &operator<<(std::ostream &stream, const Deck &deck) {
    for (std::set<Card>::const_iterator i = deck.cards.begin();
      i != deck.cards.end(); ++i) {
      stream << (*i) << std::endl;
    }
    return stream;
  }
 private:
  std::set<Card> cards;
};
 
// ðóêГ* äëÿ èãðû Гў 21
class Hand {
 public:
  Hand() : cards(), value(0) {}
  // äîáГ*âëåГ*ГЁГҐ ГЄГ*ðòû Гў ðóêó Г± ïåðåñ÷åòîì î÷êîâ
  void addCard(const Card &card) {
    cards.insert(card);
    if (card.getRankId() == 13) { // Ace
      value += ((value + 11 > 21) ? 1 : 11);
    } else if (card.getRankId() < 11) { // 0 .. 10
      value += card.getRankId();
    } else { // Jack = 2, Queen = 3, King = 4
      value += card.getRankId() - 9;
    }
  }
  int getValue() const {
    return value;
  }
  void clear() {
    value = 0;
    cards.clear();
  }
 private:
  std::set<Card> cards;
  int value;
};
 
int getNumberOfAliveHands(const std::vector<Hand> &hands) {
  int numberOfPlayers = 0;
  for (int i = 0; i < hands.size(); ++i) {
    if (hands[i].getValue() <= 21) {
      ++numberOfPlayers;
    }
  }
  return numberOfPlayers;
}
 
int main(int argc, char **argv) {
  srand(time(0));
 
  // êîëîäГ*
  Deck deck;
  // ñáðîñ ГЁ Г§Г*ïîëГ*ГҐГ*ГЁГҐ êîëîäû Г§Г*Г*Г·ГҐГ*èÿìè îò 6 äî ГІГіГ§Г*
  // ÷åòûðåõ Г¬Г*Г±ГІГҐГ©
  deck.reset(6);
  
  // 4 "ðóêè" èãðîêîâ
  std::vector<Hand> hands(4);
  
  int i = 0;
  do {
    if (hands[i].getValue() < 21) {
      Card card = deck.drow();
      hands[i].addCard(card);
      std::cout << "Player " << i << " got " << card << " and now has " <<
        hands[i].getValue() << " points." << std::endl;
    }
    if (hands[i].getValue() == 21) {
      std::cout << "Player " << i << " wins." << std::endl;
      break;
    } else if (hands[i].getValue() > 21) {
      std::cout << "Player " << i << " has lost." << std::endl;
    }
    i = (i + 1) % hands.size();
  } while (getNumberOfAliveHands(hands) > 1); // óñëîâèå îêîГ*Г·Г*Г*ГЁГї Г*Г*äî ëó÷øå ïðîäóìГ*ГІГј
 
  std::cin.get();
  return 0;
}
0
eoLithic
0 / 0 / 0
Регистрация: 05.01.2013
Сообщений: 32
01.02.2013, 09:45  [ТС] #9
Спасибо всем за советы. Проблему решил тем, что функция, раздающая очки, начала принимать в качестве параметра нынешнее количество очков у объекта

Однако, пойду улучшать свою архитектуру.
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.02.2013, 09:45
Привет! Вот еще темы с ответами:

Динамически выделить память под массив - C++
Добрый день форусчани Как можно выделить память под массив объекта класса class Save_Colection { public: pk *field; ...

Динамически выделяемый массив структур пожертвований - C++
Почитал про динамические структуры и решил для закрепления решить задачу. Я должен ввести имена и суммы пожертвований (эта инф хранится в...

Динамически расширяющийся массив, считывание из файла - C++
Добрый День! При каждом проходе по циклу, старая информация стирается, а новая записывается в другой блок, как сделать чтобы старая...

Корректно ли удаляется динамически созданный массив? - C++
Собственно, интересует нечто подобное (очень утрированно): int* i1 = new int ; ... заполняется i1 ... int* i2 = i1; i1 = new int...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
01.02.2013, 09:45
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru