Проблема создания экземпляра класса - PullRequest
2 голосов
/ 20 ноября 2010

Я создал следующий класс в Visual Studio 2010:

public class Bat : Form1
    {
        public int BatLocation;

        public void draw()
        {
            Pen batPen = new Pen(Color.Black);
            batPen.Width = 10;
            playArea.DrawRectangle(batPen, BatLocation, (picPlayArea.Height - 30), 50, 10);
        }
    }

Но когда я пытаюсь создать экземпляр класса, я получаю исключение переполнения стека, советуя мне убедиться, что у меня нет бесконечного цикла или бесконечной рекурсии. Я попытался создать экземпляр двумя разными способами, как показано ниже:

Bat bottomBat;
bottomBat = new Bat();

и

Bat bottomBat = new Bat();

Но оба способа возвращают одну и ту же ошибку, когда я пытаюсь запустить программу. Я также попробовал определение класса с и без модификатора public.

Я довольно новичок в программировании и понятия не имею, что может быть причиной этой проблемы. Я что-то не так делаю?

Редактировать: Код для класса Bat - это все, что у меня есть на данный момент, я не создал для него специальный конструктор ... Не думал, что мне это нужно?

В любом случае, вот класс Form1 во всей его полноте:

public partial class Form1 : Form
    {
        // Define various objects for the game
        public Graphics playArea;
        Bat bottomBat = new Bat();


        public Form1()
        {
            InitializeComponent();

            // Create instances of objects
            playArea = picPlayArea.CreateGraphics();
            //bottomBat = new Bat();

            // Delegate the mouseMove event for picPlayArea
            picPlayArea.MouseMove += new MouseEventHandler(picPlayArea_MouseMove);


        }

        private void picPlayArea_MouseMove(object sender, MouseEventArgs e)
        {
            bottomBat.Location = e.X;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            string msg = "Are you sure you want to exit?",
                   title = "Confirm Exit";

            DialogResult res = MessageBox.Show(msg, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (res == DialogResult.Yes)
            {
                Environment.Exit(0);
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // This is where most of the functionality is executed within the game
            playArea.Clear(Color.White);
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            timer1.Enabled = true;
        }
    }

Ответы [ 3 ]

5 голосов
/ 20 ноября 2010

Похоже, вы объединили наследование и композицию невозможным способом. Базовый тип Form1 имеет поле, объявленное как производное типа Bat. Кроме того, он использует инициализатор поля для инициализации его новым экземпляром этого типа. Понятно, что у вас есть проблема с черепашками: когда вы создаете Bat (или Form1 в этом отношении), запускается инициализатор поля - это создаст экземпляр другого Bat, который, в свою очередь, создаст еще еще один Bat и так далее до бесконечности в теории. (на практике: пока вы не исчерпаете пространство стека).

Вот простое исправление, которое должно решить проблему переполнения стека, но, возможно, не самый подходящий дизайн в «большой картине»:

public class Bat 
{
   public void Draw(Graphics playArea)
   {
       ...
   }
}

Обратите внимание, что этот тип больше не является подклассом Form1; наследуется напрямую от System.Object. Теперь ни Form1, ни Bat классы не будут демонстрировать бесконечную рекурсию при создании их экземпляров.

Трудно предложить лучшее исправление, не зная конечной цели здесь. Я предлагаю вам подумать о том, как лучше создать эти классы. Я думаю, вам нужно потратить некоторое время на изучение языка программирования C #, дизайна ОО, а также специфики WinForms. Я думаю вы действительно хотите переопределить виртуальный метод OnPaint здесь.

0 голосов
/ 20 ноября 2010

У вас есть простая проблема.

ваш класс Bat получен из Form1, а в Form1 вы создаете новый экземпляр Bat, который, в свою очередь, основан на Form1, так что создается новый экземпляр Bat.... и так повторяется до тех пор, пока ваше пространство стека не будет израсходовано.

В общем, Form1, вероятно, не должен знать о классе Bat, и что весь код, который должен знать о Bat, должен быть в классе Bat,Однако в исключительных случаях вы можете решить эту проблему следующим образом:

partial class Form1
{
  public Form1(Bat _bat)
  {
    mBat = _Bat;
  }

  protected Bat mBat;
}

и класс летучих мышей

public class Bat : Form1
{
  public Bat() :  base(this)
  {

  }
}
0 голосов
/ 20 ноября 2010

Часто причина путает свойство с его вспомогательной переменной.

Что-то вроде:

public class tmp 
{ 
    private int _x; 

    ...

    public int X(x)
    {
        X = x;
    }
...