inheritance and cxx

John Hunter jdhunter at ace.bsd.uchicago.edu
Thu May 13 08:15:39 EDT 2004


I am using pycxx 5.2.2 to implement some extension code and have a
problem relating to inheritance.  I have a pure virtual base class and
two concrete derived classes.  In the code below, everthing works fine
in that the derived classes can use the base method get, but if I try
and add a method only available to Derived2, eg, get2, I get a
compiler error on the call to 

  add_varargs_method("get2",&Derived2::get2, "get2()\n");

in Derived::init_type.

inheritance.cxx:73: error: no matching function for call to `
   Py::PythonExtension<Base>::add_varargs_method(const char[5], Py::Object
   (Derived2::*)(const Py::Tuple&), const char[8])'
/usr/local/include/python2.3/CXX/Extensions.hxx:574: error: candidates are:
   static void Py::PythonExtension<T>::add_varargs_method(const char*,
   Py::Object (T::*)(const Py::Tuple&), const char*) [with T = Base]
inheritance.cxx: In function `void initinheritance()':
inheritance.cxx:124: warning: unused variable `inheritance_module*inheritance'
error: command 'gcc' failed with exit status 1

How should I structure the code so that I can have inherited base
methods but also allow derived classes to have their own methods?

If I try defining Derived2 as 

class Derived1: public Py::PythonExtension<Derived1>, public Base

so that it gets it's own add_varargs_method I get into trouble because
both of the base classes share many functions so I get multiple
inheritance errors.

Complete example follows...


#include <iostream>
#include <cmath>
#include <utility>
#include "CXX/Extensions.hxx"

class Base : public Py::PythonExtension<Base> {
public:
  virtual Py::Object get(const Py::Tuple &args)=0;
  
  static void init_type(void);
  
};



// a mutable float
class Derived1: public Base {
public:
  Derived1(double val) : _val(val) {}
  
  
  static void init_type(void);
  
  Py::Object get(const Py::Tuple & args) {
    return Py::Float(_val ); 
  }
  
private:
  double _val;
};


// binary operations on lazy values
class Derived2: public Base {
public:
  Derived2(Base* b) : _b(b) {} 
  
  static void init_type(void);
  Py::Object get(const Py::Tuple & args) {
    return _b->get(args);
  }

  Py::Object get2(const Py::Tuple & args) {
    return _b->get(args);
  }
  
  
private:
  Base* _b;
};


void 
Base::init_type()
{
  behaviors().name("Base");
  behaviors().doc("My base class");
  add_varargs_method("get",    &Base::get,     "get()\n");
}

void 
Derived1::init_type()
{
  behaviors().name("Derived1");
  behaviors().doc("Derived 1");
}

void 
Derived2::init_type()
{
  behaviors().name("Derived2");
  behaviors().doc("Derived 2");
  add_varargs_method("get2",    &Derived2::get2,     "get2()\n");
} 



// the extension module
class inheritance_module : public Py::ExtensionModule<inheritance_module>

{
public:
  inheritance_module()
    : Py::ExtensionModule<inheritance_module>( "inheritance" )
  {
    Base::init_type();
    Derived1::init_type();
    Derived2::init_type();
    
    add_varargs_method("Derived1", &inheritance_module::new_derived1, 
		       "Derived1(x)");
    add_varargs_method("Derived2", &inheritance_module::new_derived2, 
		       "Derived2(b)");
    initialize( "The inheritance module" );
  }
  
  virtual ~inheritance_module() {}
  
private:
  
  Py::Object inheritance_module::new_derived1 (const Py::Tuple &args)
  {
    args.verify_length(1);
    double val = Py::Float(args[0]);
    return Py::Object( new Derived1(val) );
  }   
  
  
  Py::Object inheritance_module::new_derived2 (const Py::Tuple &args)
  {
    args.verify_length(1);
    if (!Base::check(args[0]))
      throw Py::TypeError("Derived2(b) expecting a base instance");
    
    Base* b = static_cast<Base*>(args[0].ptr());
    return Py::Object( new Derived2(b) );
  }   
};

extern "C"
DL_EXPORT(void)
  initinheritance(void)
{
  static inheritance_module* inheritance = new inheritance_module;
  
};











More information about the Python-list mailing list