#c #arrays
#c #массивы
Вопрос:
Я хотел бы создать игру Конвея о жизни. У меня есть два класса Cell и Board, и в Board я хочу создать ячейку типа 2D динамического массива. Я не имею ни малейшего представления, как добраться из этого массива до полей ячейки. Компилятор показывает
C:UsersJaDesktopObjectProjectObjectGameOfLifeboard.cpp:54 : ошибка: C2248: ‘Cell::state_current’: не удается получить доступ к закрытому члену, объявленному в классе ‘Cell’
Извините за мой английский.
#ifndef CELL_H
#define CELL_H
#include <iostream>
#include <cstdlib>
using namespace std;
class Cell
{
bool state_current;
bool state_future;
int neighbors;
void editCell(bool n_state);
public:
Cell();
void show();
void edit();
};
cell.cpp
#endif // CELL_H
#include "cell.h"
Cell::Cell()
{
int a=0;
a=rand()%2;
if(a==1)
state_current=true;
else
state_current=false;
state_future=false;
neighbors=0;
}
void Cell::show()
{
if(state_current==true)
cout<<'X';
else
cout<<'O';
}
void Cell::editCell(bool n_state)
{
state_current=n_state;
}
void Cell::edit()
{
int option;
cout<<"choose avaible option:n0.deadn1.alive"<<endl;
cin>>option;
while(option!=1 amp;amp; option!=0)
{
cout<<"choose avaible option"<<endl;
cin>>option;
}
if(option==1)
editCell(true);
else
editCell(false);
}
board.h
#ifndef BOARD_H
#define BOARD_H
#include "cell.h"
class Board
{
int v;
int c;
Cell **t;
public:
Board(int a=10, int b=10); //konstruktor z wartościami domyślnymi
void showBoard();
void getSize();
void createBoard();
void checkNeighborhood(int x, int y);
void rules(int x, int y);
void nextGen();
};
#endif // BOARD_H
board.cpp
#include "board.h"
Board::Board(int a,int b)
{
v=a;
c=b;
t=new Cell *[v];
for(int i=0; i<v; i )
t[i]=new Cell [c];
}
void Board::createBoard()
{
t=new Cell *[v];
for(int i=0; i<v; i )
t[i]=new Cell [c];
}
void Board::showBoard()
{
for(int i=0; i<v; i )
{
for(int j=0; j<c; j )
t[i][j].show();
cout<<endl;
}
}
void Board::getSize()
{
int a,b;
cout<<"Enter natural numbers"<<endl;
cin>>a;
cin>>b;
while(a<1 amp;amp; b<1)
{
cout<<"Board can't have this size. Enter natural numbers"<<endl;
cin>>a;
cin>>b;
}
v=a;
c=b;
}
void Board::checkNeighborhood(int x, int y)
{
for(int i=x-1; i<x 2; i )
for(int j=y-1; j<y 2; j )
if(i>=0 amp;amp; i<v amp;amp; j>=0 amp;amp; j<c)
if(!(i==x amp;amp; j==y))
if(t[i][j].state_current==true)//first crash
t[i][j].neighbors ;
}
void Board::rules(int x, int y)
{
if(t[x][y].state_current==true)
if(t[x][y].neighbors<2 || t[x][y].neighbors)
t[x][y].state_future=false;
else
t[x][y].state_future=true;
else
if(t[x][y].neighbors==3)
t[x][y].state_future=true;
else
t[x][y].state_future=false;
}
void Board::nextGen()
{
for(int i=0; i<v; i )
for(int j=0; j<c; j )
{
rules(i,j);
t[i][j].state_current=t[i][j].state_future;
}
}
Ответ №1:
Проблема именно в том, что в нем написано, что это так; вы пытаетесь изменить частный атрибут другого объекта. В этой строке:
if(t[i][j].state_current==true)//first crash
Обратите внимание, что вы обращаетесь прямо к объекту и пытаетесь ухватиться за атрибут (переменную-член), а не спрашиваете ячейку о ее состоянии.
Часть цели инкапсуляции функциональных возможностей и придания им приватности состоит в том, чтобы предотвратить проникновение других объектов внутрь и их изменение волей-неволей. Даже если вы просто выполняете проверку здесь, правильный способ сделать это — использовать объектный метод для опроса объекта. Добавьте что-то подобное в свой Cell.h и Cell.cpp как общедоступная функция:
boolean Cell::status()
{
return state_current;
}
Затем назовите это следующим образом:
if(t[i][j].status()==true)
Очевидно, что вы должны использовать тот же объектно-ориентированный подход к остальным манипуляциям, которые вы затем выполняете с ячейками. Не пытайтесь изменять ячейку напрямую, сообщите объекту, как она должна быть изменена, а затем позвольте ячейке управлять этим. Это делает ваш код многоразовым и гораздо более читаемым.
Комментарии:
1. Итак, самый простой способ решить эту проблему — создать и использовать методы set и get ячейки?
2. ДА. В краткосрочной перспективе это требует больше кода, чем традиционный подход C (императивный стиль), когда вы достигаете и делаете то, что хотите, но в долгосрочной перспективе, по мере роста проекта в размерах, это абсолютно правильный и самый простой подход.
3. Создайте функции-члены для всех поведений, которые есть у ячейки, и для всех вещей, о которых вы хотите спросить ячейку. Затем используйте их. Сделайте ячейку непрозрачной. Хотя вы можете больше не использовать этот код, в более крупном проекте это приводит к созданию кода, который можно легко извлечь и перенести в другие проекты, если вы правильно определили интерфейс к объекту.