How to extend a class without redeclaring all its methods?

F

Francois Grieu

Hello, I know C well, but not C++, and have a naive question.

I have a class defined by a library that I do not want to modify;
in my case the mpz_class of gmpxx.h (see <http://gmplib.org> ).

I want to add a member function to this class, without the hassle
of writing something for each existing function of that class.
I can make a new class with a new name, and do not need to add
any field. If have tried the following and it nearly works:


#include <iostream>
using namespace std;

#include <gmpxx.h>

// attempt at a straight extension of gmpxx's mpz_class
class myz_class : public mpz_class {
public:
// smallest n such that 2^^n is greater than absolute value
mp_bitcnt_t bitlen() {
mp_bitcnt_t n = mpz_sgn(get_mpz_t());
if (n!=0)
n = mpz_sizeinbase(get_mpz_t(), 2);
return n;
};
};

int main (void)
{
mpz_class p;
myz_class y;
p = 0;
// y = 0; // does not compile, error: no match for 'operator='
for (int i=0; i<5; ++i)
{
cout
<< "# p=" << p
<< " abs(p)=" << abs(p)
<< " y=" << y
<< " abs(y)=" << abs(y)
<< " bitlen(y)=" << y.bitlen()
<< "\n";
++p;
++y; // works!
}
return 0;
}



I have two problems:

1) it appears that the overloaded operator = did not make it from
mpz_class to myz_class even though operator ++ did.

2) short of using a macro, how do I change things in order to
write bitlen(y) much like I write abs(y)?


TIA,

Francois Grieu
 
A

Alf P. Steinbach /Usenet

* Francois Grieu, on 04.08.2010 21:46:
Hello, I know C well, but not C++, and have a naive question.

I have a class defined by a library that I do not want to modify;
in my case the mpz_class of gmpxx.h (see<http://gmplib.org> ).

I want to add a member function to this class, without the hassle
of writing something for each existing function of that class.
I can make a new class with a new name, and do not need to add
any field. If have tried the following and it nearly works:


#include<iostream>
using namespace std;

#include<gmpxx.h>

// attempt at a straight extension of gmpxx's mpz_class
class myz_class : public mpz_class {
public:
// smallest n such that 2^^n is greater than absolute value
mp_bitcnt_t bitlen()

This should be 'const'.

{
mp_bitcnt_t n = mpz_sgn(get_mpz_t());
if (n!=0)
n = mpz_sizeinbase(get_mpz_t(), 2);
return n;
};
};

int main (void)
{
mpz_class p;
myz_class y;
p = 0;
// y = 0; // does not compile, error: no match for 'operator='
for (int i=0; i<5; ++i)
{
cout
<< "# p="<< p
<< " abs(p)="<< abs(p)
<< " y="<< y
<< " abs(y)="<< abs(y)
<< " bitlen(y)="<< y.bitlen()
<< "\n";
++p;
++y; // works!
}
return 0;
}



I have two problems:

1) it appears that the overloaded operator = did not make it from
mpz_class to myz_class even though operator ++ did.

The problem is that the compiler automatically generates a copy assignment
operator for you, and it hides the operator= implementation(s) from the base class.

See the FAQ about such hiding.

A simple solution:

using mpz_class::eek:perator=;

2) short of using a macro, how do I change things in order to
write bitlen(y) much like I write abs(y)?

typedef ptrdiff_t Size;

inline Size bitlen( myz_class const& v )
{
return v.bitlen();
}


Cheers & hth.,

- Alf
 
K

Kai-Uwe Bux

Francois said:
Hello, I know C well, but not C++, and have a naive question.

I have a class defined by a library that I do not want to modify;
in my case the mpz_class of gmpxx.h (see <http://gmplib.org> ).

I want to add a member function to this class, without the hassle
of writing something for each existing function of that class.

I think, you don't want to do that. You want a way of conveniently computing
the "smallest n such that 2^^n is greater than absolute value" of a given
mpz. In rephrasing the need, you become more open to alternative solutions.
The way you phrase the question predetermines an implementation detail.
I can make a new class with a new name, and do not need to add
any field. If have tried the following and it nearly works:


#include <iostream>
using namespace std;

#include <gmpxx.h>

// attempt at a straight extension of gmpxx's mpz_class
class myz_class : public mpz_class {
public:
// smallest n such that 2^^n is greater than absolute value
mp_bitcnt_t bitlen() {
mp_bitcnt_t n = mpz_sgn(get_mpz_t());
if (n!=0)
n = mpz_sizeinbase(get_mpz_t(), 2);
return n;
};
};

I suggest, you turn that into a free-standing function:

mp_bitcnt_t bitlen( mpz_class const & arg );

int main (void)
{
mpz_class p;
myz_class y;
p = 0;
// y = 0; // does not compile, error: no match for 'operator='
for (int i=0; i<5; ++i)
{
cout
<< "# p=" << p
<< " abs(p)=" << abs(p)
<< " y=" << y
<< " abs(y)=" << abs(y)
<< " bitlen(y)=" << y.bitlen()
<< "\n";
++p;
++y; // works!
}
return 0;
}



I have two problems:

1) it appears that the overloaded operator = did not make it from
mpz_class to myz_class even though operator ++ did.

2) short of using a macro, how do I change things in order to
write bitlen(y) much like I write abs(y)?

Now, this is the right question!

mp_bitcnt_t bitlen( mpz_class const & arg ) {
...
same code as you did, but with arg.method() instead of method()
...
}



Best

Kai-Uwe Bux
 
F

Francois Grieu

I think, you don't want to do that. You want a way of conveniently computing
the "smallest n such that 2^^n is greater than absolute value" of a given
mpz. In rephrasing the need, you become more open to alternative solutions.
The way you phrase the question predetermines an implementation detail.
Indeed.


I suggest, you turn that into a free-standing function:

mp_bitcnt_t bitlen( mpz_class const & arg );

Great; I guess C++ will let me define different functions sharing the same
name and operating on different classes, which I also need. Will do the job
and avoid the troubles of defining a new class.
Now, this is the right question!

mp_bitcnt_t bitlen( mpz_class const & arg ) {
...
same code as you did, but with arg.method() instead of method()
...
}

Problem solved. Many thanks.

Francois Grieu
 
F

Francois Grieu

* Francois Grieu, on 04.08.2010 21:46:

This should be 'const'.



The problem is that the compiler automatically generates a copy assignment
operator for you, and it hides the operator= implementation(s) from the base class.

Ah that "copy assignment" gizmo makes = behave differently than ++
See the FAQ about such hiding.

A simple solution:

using mpz_class::eek:perator=;

I guess that you mean
y mpz_class::eek:perator= 0;
typedef ptrdiff_t Size;

inline Size bitlen( myz_class const& v )
{
return v.bitlen();
}

At least I fully get that one. Many thanks.

Francois Grieu
 
A

Alf P. Steinbach /Usenet

* Francois Grieu, on 04.08.2010 23:00:
Ah that "copy assignment" gizmo makes = behave differently than ++


I read<http://www.parashift.com/c++-faq-lite/assignment-operators.html#faq-12.4>
and only vaguely get what happens in the case of my code. Will learn.

That one is relevant yes.

What you're up against, though, is this:

<url: http://www.parashift.com/c++-faq-lite/strange-inheritance.html#faq-23.9>


I guess that you mean
y mpz_class::eek:perator= 0;

No, I meant what I wrote. Place that in your class definition.

At least I fully get that one. Many thanks.

You're welcome.


Cheers & hth.,

- Alf

PS: Kai-Uwe Bux, else-thread, managed to see the Big Picture. I'd follow that
advice! ;-)
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top