2010-11-20 3 views
2

Я создать следующий класс в 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 и без него.

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

Edit: Код для 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

Существует не хватает информации здесь. Можете ли вы опубликовать код для всех конструкторов класса, а также для его базовых классов? (Вы можете остановить, как только вы нажмете базовый класс, который является классом BCL) – Ani

+0

Код, который вы опубликовали (минус строка, ссылающаяся на «playArea'), работает для меня отлично, поэтому проблема должна заключаться в одной из частей, т. –

+0

Я добавил в код для класса Form1, как и требовалось –

ответ

5

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

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

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

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

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

+0

В таком случае, как бы получить доступ к объекту 'playArea' в' Form1'? У меня уже есть это публично, но когда я удаляю ': Form1' из класса' Bat', я больше не могу обращаться к этой переменной. –

+1

@ Саладин: вам нужно получить доступ к объекту 'playArea' через экземпляр' Form1' в вашем классе 'Bat'. Например: 'myForm1.playArea' –

+0

@ Саладин, если Bat расширяет Form1, тогда любая созданная летучая мышь увидит * свою собственную игру playArea, а не одну из формы, в которой она находится –

0

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

Что-то вдоль линий:

public class tmp 
{ 
    private int _x; 

    ... 

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

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

Ваш класс 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) 
    { 

    } 
} 
Смежные вопросы