inheritance and cxx

J

John Hunter

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;

};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top