chien@iitmax.iit.edu (Greg Chien) (05/02/91)
A beginner's question to C++ gurus: When compiling the following program, C++ complains that Point::Point() default constructor is not found in resolving Point p[2]. However, if Point() { x = 200; } is uncommented, ambiguous constructors error is generated in resolving Point q. Both cases are tried with HP/C++ 2.1 and Borland C++. What should be the right way to do? Thanks in advance. Greg Chien Design Processes Laboratory Institute of Design Illinois Institute of Technology chien@iitmax.iit.edu // ---------------- 8< -------- CUT HERE ---------- 8< ----------------- #include <iostream.h> class Point { int x; public: // Point() { x = 200; } Point(int xc = 100) { x = xc; } GetX() { return x;} }; int main() { Point p[2]; Point q; cout << p[1].GetX() << "\n"; cout << q.GetX() << "\nO.K.\n"; return 0; } // ---------------- 8< -------- CUT HERE ---------- 8< -----------------
cs132058@cs.brown.edu (Chris R. Brown) (05/03/91)
chien@iitmax.iit.edu (Greg Chien) writes: >class Point { > int x; >public: >// Point() { x = 200; } > Point(int xc = 100) { x = xc; } >}; >When compiling the above program, C++ complains that Point::Point() >default constructor is not found in resolving Point p[2]. However, >if Point() { x = 200; } is uncommented, ambiguous constructors error >is generated in resolving Point q. Both cases are tried with HP/C++ 2.1 >and Borland C++. What should be the right way to do? Thanks in advance. It turns out that the only way to specify arguments to the constructor when instantiating a class array is inside a brace-enclosed array initialization list: Point p[2] = { Point(50), Point(3), Point(20) }; OR Point p[2] = { 50, 3, 20 }; (The second case can only be used if the constructor takes ONE argument. In that case, the integers will be interpreted as arguments to the constructor for Point, and Point's will be implicitly created and placed in the array.) In your case, in order to specify that the default parameter be used, your code should read: Point p[2] = { Point(), Point(), Point() }; Now, this can get really awkward if your array size gets even moderately large. Some ways around this: ------------------------------------------------------------------------ 1) Create a class PointArray with a constructor that uses a loop to send identical arguments to the Point class: class PointArray { private: Point **p; public: PointArray(int sz = DEFAULT) { int i; p = new Point *[sz]; for (loop=0; loop < sz; loop++) p[loop] = new Point(); } : } This might not be worth it if you don't add any new functionality to the array. ------------------------------------------------------------------------- 2) Have two constructors for Point, one with 1 argument and the other w/ none: public: Point() { x = DEFAULT } Point(int new_x) { x = new_x } The reason the compiler got confused over your overloaded constructor is that > Point() { x = 200; } > Point(int xc = 100) { x = xc; } can both be interpreted as taking no arguments (for the second constructor, if there is no argument, the default is used. -------------------------------------------------------------------------- It seems odd that C++ would allow class arrays to be simply defined if the constructor takes no arguments, as in public: ClassX() { ... }; : : ClassX arr[2]; but can't handle a class array w/ a constructor that DOES take arguments: public: ClassZ(int n) { ... }; : : ClassZ arr(3)[2]; // ERROR The reason is that the preprocessor sees the parentheses as declaring some sort of function called "arr" with a ClassZ return type. - Chris R. Brown ///////////////////////////////////////////////////////////////////////////
steve@taumet.com (Stephen Clamage) (05/03/91)
chien@iitmax.iit.edu (Greg Chien) writes: >When compiling the following program, C++ complains that Point::Point() >default constructor is not found in resolving Point p[2]. However, >if Point() { x = 200; } is uncommented, ambiguous constructors error >is generated in resolving Point q. >class Point { > ... >public: >// Point() { x = 200; } > Point(int xc = 100) { x = xc; } >}; > Point p[2]; A default constructor is required to initialize the array 'p'. Under the latest language rules, any constructor requiring no parameters (such as 'Point(int=100);') will serve, but this is also noted as a recent extension. With future compilers, the could should work as given. With many current compilers (including Borland C++ 2.0) the 'Point()' constructor is required, as that was the earlier rule. But the combination Point(); Point(int = 100); is ambiguous, since neither constructor needs to be called with any parameters. You can achieve exactly the effect of your original code by using Point() { x = 100; } Point(int xc) { x = xc; } This satisfies both old and new language rules. -- Steve Clamage, TauMetric Corp, steve@taumet.com