简体   繁体   中英

Problem creating instance of a class

I've create the following class in 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);
        }
    }

But when I try to create an instance of the class, I get a stack overflow exception, advising me to make sure that I don't have an infinite loop or infinite recursion. I have tried creating the instance two different ways, as below:

Bat bottomBat;
bottomBat = new Bat();

and

Bat bottomBat = new Bat();

But both ways return the same error when I try to run the program. I've also tried the class definition with and without the public modifier.

I'm pretty new to programming and have no idea what might be causing this problem. Am I doing something wrong?

Edit: The code for the Bat class is everything I have at the moment, haven't created a specific constructor for it... Didn't think I needed to?

Anyway, here is the Form1 class in its entirety:

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

It appears you have combined inheritance and composition in an impossible sort of way. The base Form1 type has a field declared to be of the derived Bat type. In addition, it uses a field-initializer to initialize it to a new instance of that type. Clearly, you have a turtles-all-the-way-down issue: when you create a Bat (or a Form1 for that matter), the field-initializer will run - this will create an instance of another Bat , which in turn will create yet another Bat , and so on, ad-infinitum in theory. (in practice: until you run out of stack-space).

Here's a simple fix that should solve the stack-overflow issue, but may not be the most appropriate design in the 'big-picture':

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

Notice how this type no longer subclasses Form1 ; it inherits directly from System.Object . Now neither the Form1 nor the Bat classes will exhibit infinite recursion when instances of them are created.

It's hard to suggest the best fix without knowing the ultimate aim here. I suggest you give some thought to the best way to design these classes. I would think you need to spend some time learning about the C# programming language, OO design, as well as WinForms specifics. I think you're actually looking to override the OnPaint virtual method here.

Often the cause is confusing a property with its backing variable.

Something along the lines of:

public class tmp 
{ 
    private int _x; 

    ...

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

You have a simple problem.

your class Bat is derived from Form1, and in Form1 you create a new instance of Bat, which in turn is based on Form1 so that creates a new instance of Bat.... and so it repeats until your stack space is used up.

In general, Form1 probably should not know about the class Bat, and that all code that needs to know about Bat should be in the Bat class. However, in exceptional circumstances, you can solve this issue like this:

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

  protected Bat mBat;
}

and on the Bat class

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

  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM