Solved

no appropriate default constructor available.

Posted on 2003-10-31
9
1,173 Views
Last Modified: 2007-12-19
Thanks for your comment, now I know that if I accept is (Position p[]) then I should use pointer to a Position* , if (float a[]) then I should use float*. And now I know that return an array. Thanks! 

Now I got another question I try to write the class MyOpenGLScene which inherits publicly from OpenGLScene. I try to add to the class an array which stores pointer to triangle and write a constructor which will accept the following parameters:
The name of the scene (as a char*), the width, the height , the color depth and a fullscreen flage(FALSE).
So I write like this:
 MyOpenGLScene::MyOpenGLScene (char* title, int width, int height, int bits, bool fullscreenflag)
{
      //this->title = title;
      //this->width = width;
      //this->heigh = heigh;
      //this->bits = bits;
      //this->fullscreenflag = fullscreenflag;
}
Then I got this error: C2512: 'OpenGLScene' : no appropriate default constructor available. So I don’t understand what going wrong, because I think the way I write is fine. I don’t know this error how to fix it, because I also new with C++, so can anyone explain to me why I will got this error? And what should I do if I meet with this kind of error again.

Following is my all class and code.
OpenGLScene.h
#define FALSE 0

class OpenGLScene {      
      HGLRC hRC;
      HWND hWnd;
      HINSTANCE hInstance;
      HDC hDC;
      BOOL done;
      bool fullscreen;
      MSG msg;
      GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
      int InitGL(GLvoid);
      BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag);
      
public:
      OpenGLScene (char* title, int width, int height, int bits, bool fullscreenflag);
      GLvoid KillGLWindow(GLvoid);
      virtual void addTriangle (Triangle *T) = 0;
      virtual int DrawGLScene(GLvoid) = 0;
      virtual void DrawTriangle (Triangle *T) = 0;
      int start ();
};

#endif


MyOpenGLScene.cpp
#include "OpenGLScene.h"

class MyOpenGLScene: public OpenGLScene
{
      Triangle* T;
      //char* title;
      //int width, heigh, bits;
      //bool fullscreenflag;

  public:
    //MyOpenGLScene (char* title, int width, int height, int bits, bool fullscreenflag);
      MyOpenGLScene (char* title, int width, int height, int bits, bool fullscreenflag);
      void addTriangle (Triangle *T);
      int DrawGLScene(GLvoid);
      void DrawTriangle (Triangle *T);
};

Triangle.h
#include "Position.h"
class Triangle
{
      float red,green,blue,point;
      Position pos[3];
            
public:
      Triangle (Position p[]);
      //~Triangle();
      void setColor(float red,float green,float blue);
      float getRed();
      float getGreen();
      float getBlue();
      Position* getVertices();
};

Hope someone can help me solve my problem. Thanks

From:sally
0
Comment
Question by:sally1980
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
9 Comments
 
LVL 8

Accepted Solution

by:
Exceter earned 20 total points
ID: 9662191
Try this,

class OpenGLScene {    
     HGLRC hRC;
    HWND hWnd;
    HINSTANCE hInstance;
    HDC hDC;
    BOOL done;
    bool fullscreen;
    MSG msg;
    GLvoid ReSizeGLScene(GLsizei width, GLsizei height);
    int InitGL(GLvoid);
    BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag);
   
public:
    OpenGLScene(){}
    OpenGLScene (char* title, int width, int height, int bits, bool fullscreenflag);
    GLvoid KillGLWindow(GLvoid);
    virtual void addTriangle (Triangle *T) = 0;
    virtual int DrawGLScene(GLvoid) = 0;
    virtual void DrawTriangle (Triangle *T) = 0;
    int start ();
};

Exceter
0
 
LVL 15

Expert Comment

by:efn
ID: 9662197
See my comment on this question in the Programming area:

http://www.experts-exchange.com/Programming/Q_20784791.html
0
 
LVL 8

Expert Comment

by:Exceter
ID: 9664273
You also have to add a constructor to the OPenGLScene base class, as I demonstrated above, because it does not define a default constructor either. This is necessary because the constructor for the parent classes are called before the constructor for the derived class. For example,

class test1
{
      public:
            test1(int x){}
};

class test2 : public test1
{
      public:
            test2(){}
};

Will generate an error message similar to this, deending on your compiler,

Error E2251 C:\CPP\Test.cpp 16: Cannot find default constructor to initialize base class 'test1' in function test2::test2()

Similarly,

class test1
{
      public:
            test1(){}
};

class test2 : public test1
{
      public:
            test2(int x){}
};

Will generate an error similar to this,

>> Error E2285 C:\CPP\Test.cpp 24: Could not find a match for 'test2::test2()' in function main()

So, in actuality, you need to define a default constructor in both the base class and in the derived class.

Cheers!
Exceter
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 15

Expert Comment

by:efn
ID: 9664405
Just to clarify, Exceter and I have provided two different solutions--you can use either one, depending on what you need in the code that uses this class.  If you really need a default constructor, you can define one, as Exceter suggested, and if you don't really need a default constructor, you can use the constructor you already have, as I suggested.

--efn
0
 
LVL 8

Expert Comment

by:Exceter
ID: 9664901
>> Exceter and I have provided two different solutions

Not really. I added a default constructor in the base class you suggesed adding one in the derived class, or not using a default constructor.

>> If you really need a default constructor, you can define one, as Exceter suggested, and if you don't really need a default constructor, you can use the constructor you already have, as
>> I suggested.

That's incorrect. The definition of a default constructor in the base class is manditory if you want to derive another class from it. The code will not compile if the base class does not have a default constructor, even if the dereived class does. For example,

class test1
{
    public:
         test1(int x){}
};

class test2 : public test1
{
    public:
          test2(){}
         test2(int y){}
};

Will give you an error similar to this,

Error E2251 C:\CPP\Test.cpp 16: Cannot find default constructor to initialize base class 'test1' in function test2::test2()
Error E2251 C:\CPP\Test.cpp 17: Cannot find default constructor to initialize base class 'test1' in function test2::test2(int)

The default constructor is necessary to construct the base class members before the derived class's consturctor is called and in like manner the destructor of test2 will be called before the destructor for test1. For example,

class test1
{
    public:
         test1(){ cout << "test1 being constructed." << endl; }
         ~test1(){ cout << "test1 being destroyed." << endl; }
};

class test2 : public test1
{
    public:
          test2(){ cout << "test2 being constructed." << endl; }
          ~test2(){ cout << "test2 being destroyed." << endl; }
};

...

test2 t;

-- output --
test1 being constructed.
test2 being constructed.
test2 being destroyed.
test1 being destroyed.

Therefore, the default constructor is required in the base class, as I demonstrated in my initial post, just so you can use the constructor that is already defined in MyOpenGLScene. If you want you can also define a default constructor for MyOpenGLScene but you dont have to. Although it is bad form not to do so.

Cheers!
Exceter
0
 
LVL 15

Expert Comment

by:efn
ID: 9665170
efn>> Exceter and I have provided two different solutions

Exceter>> Not really. I added a default constructor in the base class you suggesed adding one in the derived class, or not using a default constructor.

Yes, really.  I wasn't ingenious enough to suggest adding a default constructor, so I just suggested using the existing parameterized constructor.  However, my solution was defective because I guessed that the message was coming from an attempt to construct a derived object and I didn't notice that the derived class was trying to use a nonexistent default constructor for the base class.  So they really are two different solutions, mine just wouldn't work, and my statement that either would work was bogus.  Sorry, Sally!

efn>> If you really need a default constructor, you can define one, as Exceter suggested, and if you don't really need a default constructor, you can use the constructor you already have, as
efn>> I suggested.

Exceter>>That's incorrect. The definition of a default constructor in the base class is manditory if you want to derive another class from it. The code will not compile if the base class does not have a default constructor, even if the dereived class does.

I now agree that the original parameterized derived class constructor had a problem in itself and using it would not get the code to compile.  However, I don't agree with the statement that the base class must have a default constructor.  It's true that Exceter's example will not compile and it's true that adding a default constructor to the base class will get it to compile.  However, it's not true that this is the only way to get it to compile.  Here's another way:

class test2 : public test1
{
    public:
            test2() : test1(0){}
            test2(int y) : test1(y){}
};

This compiles without a default constructor in the base class test1.  Similarly, Sally could fix her code by having MyOpenGLScene initialize OpenGLScene in its initialization list.  Once again, we have a choice of two valid solutions!  Unless I blew it again.

--efn
0
 
LVL 8

Expert Comment

by:Exceter
ID: 9665259
>> However, I don't agree with the statement that the base class must have a default constructor.

True, you can do it that way. However, I think that your second example, although legal, has a design flaw because you are then required to do this in every class you derive from test1. This is annoying and easily forgotten. Also, the overhead of passing parameters to the constructor is probably slower than hardcoding them into the initialization list of a default constructor.

Exceter
0
 
LVL 9

Expert Comment

by:tinchos
ID: 10242417
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Accept: Exceter {http:#9662191}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question