Multiple Inheritance problem (I think)

Started by
3 comments, last by Shannon Barber 18 years, 8 months ago
Im writing a tutorial for NeHe on how to separate your engine into loadable modules and how to separate generic code that works on both Linux and Windows. When compiling I get this error: g++ -fPIC -Wall -pedantic -ansi glx/renderer_glx.cc -c g++ -fPIC -Wall -pedantic -ansi glx/renderer_glx_factory.cc -c glx/renderer_glx_factory.cc: In function `iRenderer_x11* renderer_x11_factory() ': glx/renderer_glx_factory.cc:5: error: cannot allocate an object of type ` cRenderer_glx' glx/renderer_glx_factory.cc:5: error: because the following virtual functions are abstract: ../renderer.hpp:13: error: virtual bool iRenderer::m_set_resolution(unsigned int, unsigned int) renderer_x11.hpp:34: error: virtual bool iRenderer_x11::m_render_frame() ../renderer.hpp:16: error: virtual void iRenderer::m_add_cube(float, float) make: *** [glx/renderer_glx_factory.o] Error 1 Im using multiple inheritance here and it inherits code from the wrong class. It should inherit from cOpenGL_renderer but instead it inherits from iRenderer_x11 which does nothing. I had the same problem in the Windows version which I solved by randomly messing around with the class declarations :P . My interfaces and classes:

// Generic inteface used in AI, physics modules et.c.:
class iRenderer
 {
  public:
  virtual ~iRenderer() { }
  
  virtual bool m_set_resolution(uint a_width, uint a_height) = 0;
  
  virtual bool m_render_frame(void) = 0;
  virtual void m_add_cube(float a_pos, float a_size) = 0;
  virtual bool m_kill_window(void) = 0;
  
  enum {m_default_screen_width = 1024 };
  enum {m_default_screen_height = 768 };
 }; // end class iRenderer


// X11 interace used when creating window in Linux
class iRenderer_x11 : public iRenderer
 {
  public:
  virtual bool m_pure_virtual(void) { return true; }
  virtual bool m_create_x11_window(bp_x11_window &a_bp_x11_window) = 0;

  virtual bool m_render_frame(void) = 0;

  virtual void m_release(void) { delete this; }

 }; // end class iRenderer_x11 : virtual public iRenderer

typedef iRenderer_x11* x11_renderer_factory_ptr();

// And the one for windows:
class iRenderer_win32 : virtual public iRenderer
 {
  public:
  virtual ~iRenderer_win32() { delete this; }
  
  virtual bool m_create_win32_window(sWin32_window_bp *a_win32_window) = 0;
  virtual bool m_swap_buffers(void) = 0;
  

 }; // end class iRenderer_win32 : public virtual iRenderer

// Then we have our OpenGL classes that does all the actual rendering:
class cOpenGL_renderer : public iRenderer
 {
  public:
  cOpenGL_renderer() { m_rot = 0.0f; }
  virtual bool m_render_frame(void);
  virtual void m_add_cube(float a_pos, float a_size);
  virtual int  m_initGL(void);
  virtual int  m_load_bmp(char *filename, sTextureImage *texture);
  virtual bool m_set_resolution(uint a_width, uint a_height);
  
  protected:
  float m_rot;
 }; // end class cOpenGL_renderer : public virtual cRenderer

// And its here the problem lies:
class cRenderer_glx : public iRenderer_x11, public cOpenGL_renderer
 {
  protected:
  GLXContext m_ctx;
  bp_x11_window *m_x11_window;

  int m_attrListSgl[10];

  int m_attrListDbl[11];

  public:
  cRenderer_glx();
  virtual bool m_pure_virtual(void) { return false; }
  virtual bool m_create_x11_window(bp_x11_window &a_bp_x11_window);
  virtual bool m_kill_window(void);

  virtual void m_release(void) { delete this; }
 }; // end class cRenderer_glx : virtual public cOpenGL_renderer , public iRenderer_x11

// renderer_glx_factory.cc:
#include "renderer_glx.hpp"

extern "C" iRenderer_x11* renderer_x11_factory()
 {
  return new cRenderer_glx;
 } // end extern "C" iRenderer_x11* renderer_x11_factory()


// And finally the windows one:
class cWGL_renderer : virtual public cOpenGL_renderer , public iRenderer_win32
 {
  public:
         
  virtual bool m_create_win32_window(sWin32_window_bp *a_win32_window);
  virtual bool m_swap_buffers(void);
  virtual bool m_kill_window(void);
  
  protected:
  sWin32_window_bp    *m_win32_window;
 }; // end class cWGL_renderer : public virtual cOpenGL_renderer , public virtual iRenderer_win32



Something tells me I need to use RTTI and dynamic_cast and stuff to solve this. I would ofcourse prefer not to since im not doing anything complicated here, I just want it to link from a class which has an implementation.
Advertisement
May i suggest spending some time reading this find out the difference between multiple & virtual inheritance, when & where to use them. May i also suggest thinking of an alternative design instead the current one.
Interesting.

Consider inheriting iRenderer_win32 and iRenderer_win32 from cOpenGL_renderer.

Kuphryn
What does cRenderer_opengl look like?

Also, consider template.

Kuphryn
Interfaces are a decent example for virtual inheritence.

Architecturally, you have combined the Window Manager with the Renderer which is problematic. Consider using seperare classes such as a cRender_ogl, and a cWM_X11 & cWM_Win32. This would match the OGL model.
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement