Thread: problems with constructor

  1. #1
    Registered User
    Join Date
    Apr 2006
    Posts
    3

    problems with constructor

    It has been far too long since I have coded anything and I'm stumbling over something that should be obvious. If someone could point me in the right direction I'd greatly appreciate it.

    I have:

    A "Square" class representing a square on a checker board:
    Code:
    class Square {
             public:
                            Square(int);
            void            print_square();
             private:
            int             color;
            static const char       red[3];
            static const char       black[3];
    };
    And a "Board" class which is basically just an 2-D array of Squares:
    Code:
    class Board {
             public:
                            Board();
            void            print_board();
             private:
            Square          board[8][8];
    };
    Where I'm having problems is in calling the Square::Square(int) constructor from my Board::Board() constructor:
    Code:
    Board::Board () {
            for ( int row = 0; row < 8; row++ )
                    for ( int col = 0; col < 8; col++ ) {
                            int temp = (col + row) % 2;
                            Square board[col][row]( temp );
                    }
    }
    When I compile I get:
    Code:
    dberg@ubuntu:~/Desktop/Checkers$ g++ -c Board.cpp
    Board.cpp: In constructor ‘Board::Board()’:
    Board.cpp:20: error: no matching function for call to ‘Square::Square()’
    Board.cpp:7: note: candidates are: Square::Square(int)
    Board.hh:4: note:                 Square::Square(const Square&)
    Board.cpp:24: error: variable-sized object ‘board’ may not be initialized
    Board.cpp:24: error: no matching function for call to ‘Square::Square()’
    Board.cpp:7: note: candidates are: Square::Square(int)
    Board.hh:4: note:                 Square::Square(const Square&)
    I'm not sure what the problem is. Perhaps I've lost my grasp on how arrays are handled, or maybe its something else.

    Any tips?

    --Dave

  2. #2
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    You are getting all of those errors because you need a default constructor. When you instantiate an object of type Board, an 8-by-8 array of Square objects must be contructed. This is done by calling the default constructor which you have not defined. Make a default constructor for your Square class and those errors should disappear. Then I'd suggest some kind of Set member function for the Square class as well that you can call inside that double loop to set whatever value you are trying to set instead of calling another constructor.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    3
    Quote Originally Posted by hk_mp5kpdw
    You are getting all of those errors because you need a default constructor. When you instantiate an object of type Board, an 8-by-8 array of Square objects must be contructed. This is done by calling the default constructor which you have not defined. Make a default
    My text from college states, "If you fail to write a constructor in a class ..., the compiler automatically supplies one for you." Is this no longer the case?

    Quote Originally Posted by hk_mp5kpdw
    constructor for your Square class and those errors should disappear. Then I'd suggest some kind of Set member function for the Square class as well that you can call inside that double loop to set whatever value you are trying to set instead of calling another constructor.
    Since the color of a square on a checker board can't really change once the board is made a "set_color" function doesn't make a lot of sense. Infact, at somepoint (I've relearned a few more things) I will probably make that data member a const. If I'm not mistaken, a set_color function wouldn't be possible at that point.

    I have a hard time believing that I can't set the color of the square at the time it is created instead of doing that later.

    --Dave

  4. #4
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You are calling the constructor incorrectly.

    The constructor for Square is:

    Code:
    Square(int);
    The constructor for Board is:
    Code:
    Board();
    Yet you do this:
    Code:
    Square board[col][row]( temp );
    Code:
    class Square 
    {
      public:
        Square(int) { //Zero out members here }
        void            print_square();
      private:
         int             color;
         static const char       red[3];
         static const char       black[3];
    };
    
    class Board 
    {
      public:
        Board() {m_pSquare=NULL }
        virtual ~Board() {delete m_pSquare;   //Check for validity here if MSVC 6}
        void Create() {m_pSquare=new Square(0); }
        void print_board();
      private:
        Square       *m_pSquare;
    Square takes an integer in the constructor but you never use it or even give the parameter a variable name.

    I'm assuming you want one Square so you use static. But from what I see your entire design is heading in the wrong direction.

    First encapsulate access to a simple linear array.
    Second make a class that uses that class to present a game board to the user.

    Or just make a Board class that encapsulates an array.

    A default constructor will take no parameters, because the compiler has no way of knowing how many parameters you want or need.

    Code:
    class Foo
    {
       int m_iX;
       public:
         void SetX(int value) {m_iX=value;}
         int GetX() {return m_iX;}
    };
    
    Foo Object;      //Default constructor is called, m_iX's value is undefined here
    Object.SetX(5);  //Now m_iX's value is 5
    Good habit to get into:

    1. Always provide your own constructor.
    2. Always provide a virtual destructor.

    Don't rely on the compiler's default constructor to help you at all.
    Last edited by VirtualAce; 04-01-2006 at 02:22 PM.

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    If you don't specify any constructor, then it will create a default one for you. You have however specified a contructor that takes an int argument and the compiler will take that as the only constructor available. When you instantiate an instance of type Board, the compiler will therefore not be able to find the default constructor necessary to create the Square board[8][8] member of your Board class.

    In a certain sense, you don't need to know the color of the square. That is just a visual que us humans find easy to deal with. To the Board object, the color of the square can be infered simply by its index values; i.e. [0][0] is red, [0][1] is black... [1][0] is red, [1][1] is black, etc.. What you must keep track of is the color of the piece on a given square, not the color of the square itself and this is what I had thought the color member represented.

    If you really want to assign a color to the squares and make them a const member then I would suggest something along the lines of this:
    Code:
    #include <iostream>
    
    typedef enum color{ RED, BLACK };
    
    class Square
    {
        const color type;
        static int sequence;
        static color GetColor()
        {
            if( (sequence / 8) % 2 == 0 ) return static_cast<color>(sequence%2);
            else return static_cast<color>((sequence+1)%2);
        }
    public:
        Square() : type(GetColor()) { ++sequence; }
        friend std::ostream& operator<<(std::ostream&,const Square&);
    };
    
    std::ostream& operator<<(std::ostream& os,const Square& square)
    {
        if( square.type == RED )
            os << "RED";
        else os << "BLACK";
    
        return os;
    }
    
    int Square::sequence = 0;
    
    
    // Board class
    class Board
    {
        Square board[8][8];
    public:
        void print()
        {
            for( int a = 0; a < 8; ++a )
                for( int b = 0; b < 8; ++b )
                {
                    std::cout << "Square[" << a << "]" << "[" << b << "] is "
                        << board[a][b] << std::endl;
                }
        }
    };
    
    
    int main()
    {
        Board board;
        board.print();
    
        return 0;
    }
    This prints out:
    Code:
    Square[0][0] is RED
    Square[0][1] is BLACK
    Square[0][2] is RED
    Square[0][3] is BLACK
    Square[0][4] is RED
    Square[0][5] is BLACK
    Square[0][6] is RED
    Square[0][7] is BLACK
    Square[1][0] is BLACK
    Square[1][1] is RED
    Square[1][2] is BLACK
    Square[1][3] is RED
    Square[1][4] is BLACK
    Square[1][5] is RED
    Square[1][6] is BLACK
    Square[1][7] is RED
    Square[2][0] is RED
    Square[2][1] is BLACK
    Square[2][2] is RED
    Square[2][3] is BLACK
    Square[2][4] is RED
    Square[2][5] is BLACK
    Square[2][6] is RED
    Square[2][7] is BLACK
    Square[3][0] is BLACK
    Square[3][1] is RED
    Square[3][2] is BLACK
    Square[3][3] is RED
    Square[3][4] is BLACK
    Square[3][5] is RED
    Square[3][6] is BLACK
    Square[3][7] is RED
    Square[4][0] is RED
    Square[4][1] is BLACK
    Square[4][2] is RED
    Square[4][3] is BLACK
    Square[4][4] is RED
    Square[4][5] is BLACK
    Square[4][6] is RED
    Square[4][7] is BLACK
    Square[5][0] is BLACK
    Square[5][1] is RED
    Square[5][2] is BLACK
    Square[5][3] is RED
    Square[5][4] is BLACK
    Square[5][5] is RED
    Square[5][6] is BLACK
    Square[5][7] is RED
    Square[6][0] is RED
    Square[6][1] is BLACK
    Square[6][2] is RED
    Square[6][3] is BLACK
    Square[6][4] is RED
    Square[6][5] is BLACK
    Square[6][6] is RED
    Square[6][7] is BLACK
    Square[7][0] is BLACK
    Square[7][1] is RED
    Square[7][2] is BLACK
    Square[7][3] is RED
    Square[7][4] is BLACK
    Square[7][5] is RED
    Square[7][6] is BLACK
    Square[7][7] is RED
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  6. #6
    Registered User
    Join Date
    Apr 2006
    Posts
    3
    Quote Originally Posted by hk_mp5kpdw
    If you don't specify any constructor, then it will create a default one for you. You have however specified a contructor that takes an int argument and the compiler will take that as the only constructor available. When you instantiate an instance of type Board, the compiler will therefore not be able to find the default constructor necessary to create the Square board[8][8] member of your Board class.
    I think where I'm confused is that I was imagning Square board[8][8] as an array of pointers instead of an array of objects. If I'm understanding things right, when I create a Board object the compiler immediately trys to create 64 Square objects and arranges them in the array then calls the constructor. They way I have been thinking of it is when I create the Board object, the constructor is called immediately and the Square objects are created in the Board constructor.

    Assuming that the objects are created and then the constructor is called, I'm now more inclined to believe that I can't create the board staticly and set the color in a Constructor. Am I thinking on the right track now?

    If I change
    Code:
            Square          board[8][8];
    to
    Code:
            Square*          board[8][8];
    and
    Code:
                            Square board[col][row]( temp );
    to
    Code:
                           board[col][row] = new Square( temp );
    it works.

    Can I do the same thing with static memory allocation?



    Quote Originally Posted by hk_mp5kpdw
    In a certain sense, you don't need to know the color of the square. That is just a visual que us humans find easy to deal with. To the Board object, the color of the square can be infered simply by its index values; i.e. [0][0] is red, [0][1] is black... [1][0] is red, [1][1] is black, etc.. What you must keep track of is the color of the piece on a given square, not the color of the square itself and this is what I had thought the color member represented.
    This is a good point, and I may very well get rid of the color member in the future. Either way, I want to understand why what I have doesn't work, and though I'm closer I'm still not quite there.

    Thanks much.

  7. #7
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    the array can be initialized just as you would with an ordinary data type:

    Code:
    struct square { square(int i) { } };
    
    int
    main()
    {
    	square s[4] = {13, 2, 5, 6};
    	square m[3][4] = { {13, 2, 5, 6}, {7, 2, 8, 4}, {9, 5, 0, 7} };
    }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. calling copy constructor from template
    By Ancient Dragon in forum C++ Programming
    Replies: 3
    Last Post: 09-28-2005, 01:54 PM
  2. constructors
    By shrivk in forum C++ Programming
    Replies: 7
    Last Post: 06-24-2005, 09:35 PM
  3. Need help in classes
    By LBY in forum C++ Programming
    Replies: 11
    Last Post: 11-26-2004, 04:50 AM
  4. Call constructor within constructor. How to?
    By xErath in forum C++ Programming
    Replies: 10
    Last Post: 11-18-2004, 05:30 PM
  5. Problems: Operator overloading.
    By Dual-Catfish in forum C++ Programming
    Replies: 17
    Last Post: 06-18-2002, 06:38 PM