2010-11-20 26 views
2

j'ai créer la classe suivante dans Visual Studio 2010:Problème créant instance d'une classe

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); 
     } 
    } 

Mais lorsque je tente de créer une instance de la classe, je reçois une exception de débordement de pile, me conseillant de assurez-vous que je n'ai pas une boucle infinie ou une récursion infinie. J'ai essayé de créer l'instance de deux façons différentes, comme ci-dessous:

Bat bottomBat; 
bottomBat = new Bat(); 

et

Bat bottomBat = new Bat(); 

Mais les deux sens revenir la même erreur lorsque je tente d'exécuter le programme. J'ai également essayé la définition de classe avec et sans le modificateur public. Je suis assez nouveau à la programmation et n'ai aucune idée de ce qui pourrait causer ce problème. Est-ce que je fais quelque chose de mal?

Edit: Le code de la classe Bat est tout ce que j'ai en ce moment, ne l'ai pas créé un constructeur spécifique pour cela ... Ne pense pas que je devais?

Quoi qu'il en soit, voici la classe Form1 dans son intégralité:

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

Il n'y a pas assez d'informations ici. Pouvez-vous poster le code pour tous les constructeurs de la classe ainsi que ceux de ses classes de base? (Vous pouvez vous arrêter une fois que vous avez atteint une classe de base qui est une classe BCL) – Ani

+0

Le code que vous avez posté (moins la ligne référençant 'playArea') fonctionne très bien pour moi, donc le problème doit se situer dans l'une des parties que vous n'avez pas t poste. –

+0

J'ai ajouté dans le code de la classe Form1, comme demandé –

Répondre

5

Il semble que vous avez combiné l'héritage et la composition dans une sorte de façon impossible. Le type de base Form1 a un champ déclaré comme étant de type dérivé Bat. En outre, il utilise un initialiseur de champ pour l'initialiser à une nouvelle instance nouvelle de ce type. De toute évidence, vous avez un problème tortues-tout-le-bas: lorsque vous créez un Bat (ou un Form1 d'ailleurs), l'initialiseur de champ va s'exécuter - cela va créer une instance d'un autre Bat, qui à son tour créer encore un autreBat, et ainsi de suite, ad-infinitum en théorie. (en pratique: jusqu'à épuisement de l'espace de pile).

Voici une solution simple qui devrait résoudre le problème pile débordement, mais peut-être pas la conception la plus appropriée dans le « big picture »:

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

Remarquez comment ce type sous-classe plus Form1; il hérite directement de System.Object. Maintenant, ni les classes Form1 ni les classes Bat ne présenteront une récursion infinie lorsque des instances de ces classes sont créées.

Il est difficile de suggérer le meilleur fixer sans connaître le but ultime ici. Je vous suggère de réfléchir à la meilleure façon de concevoir ces classes. Je pense que vous avez besoin de passer du temps à apprendre sur le langage de programmation C#, OO design, ainsi que des spécificités WinForms. I pense que vous cherchez actuellement à remplacer la méthode virtuelle OnPaint ici.

+0

Dans ce cas, comment puis-je accéder à l'objet 'playArea' dans' Form1'? Je l'ai déjà comme public, mais quand je supprime le ': Form1' de la classe' Bat', je ne peux plus accéder à cette variable. –

+1

@Saladin: Vous devez accéder à l'objet 'playArea' via une instance de' Form1' dans votre classe 'Bat'. Par exemple: 'myForm1.playArea' –

+0

@Saladin si Bat étend Form1, alors toutes les chauves-souris créées voient * son propre playArea, pas une de la forme dans laquelle il se trouve. –

0

Souvent, la cause est source de confusion une propriété avec sa variable de support.

Quelque chose le long des lignes de:

public class tmp 
{ 
    private int _x; 

    ... 

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

Vous avez un problème simple.

votre classe Bat est dérivée de Form1, et dans Form1 vous créez une nouvelle instance de Bat, qui à son tour est basée sur Form1 afin de créer une nouvelle instance de Bat .... et ainsi elle se répète jusqu'à votre espace de pile est épuisé. En général, Form1 ne devrait probablement pas connaître la classe Bat, et que tout le code qui doit en savoir plus sur Bat devrait être dans la classe Bat. Cependant, dans des circonstances exceptionnelles, vous pouvez résoudre ce problème comme celui-ci:

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

    protected Bat mBat; 
} 

et sur la classe Bat

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

    } 
}