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