non-virtual overloading and performance issue

T

toton

Hi,
I want a few of my class to overload from a base class, where the
base class contains common functionality. This is to avoid repetition
of code, and may be reducing amount of code in binary, not to get
polymorphic behavior.
None of them has virtual methods, and are self contained (no
destructor at all) thus do not have a chance to have memory error.
Thus the derived classes has additional functionality, not additional
data.

Now, will the derived class suffers any performance penalty, if I
compare it to a single class which contains all of the functionality.

Second, if I want to suppress some of the functionality, is it ok to
have a private inheritance and forwarding the functionality which I
need from base class ?
Or delegation is a better way ( which adds one extra level of
indirection) ?

some of such inheritance are actually from stl container classes, like
deque and other, where I need to give a range support (like
boost::sub_range ) with a get_range method,
or want to remove some functionality like erase, assign, push_front and
pop_back.

Thanks
abir
 
?

=?iso-8859-1?q?Kirit_S=E6lensminde?=

toton said:
Hi,
I want a few of my class to overload from a base class, where the
base class contains common functionality. This is to avoid repetition
of code, and may be reducing amount of code in binary, not to get
polymorphic behavior.
None of them has virtual methods, and are self contained (no
destructor at all) thus do not have a chance to have memory error.
Thus the derived classes has additional functionality, not additional
data.

Now, will the derived class suffers any performance penalty, if I
compare it to a single class which contains all of the functionality.

It shouldn't. If the binary is smaller it may even be faster. As always
with optimisation though you need to measure the alternatives. If the
one you pick first is fast enough then don't worry about it.

You are introducing extra coupling between the classes though. This may
become a maintenance problem, but again it all depends on the exact
classes involved and their implementation.

Normally if the code is co-incidentally the same then I would repeat it
in order to reduce the coupling between the classes and reduce the
chances of errors introduced when one class needs slightly different
behaviour. Deciding whether or not the similarity of behaviour is
co-incidental or not isn't always so easy.
Second, if I want to suppress some of the functionality, is it ok to
have a private inheritance and forwarding the functionality which I
need from base class ?

This is fine, but only if you use private inheritance. Don't be lazy
and derive publicly in order to skip typing the using directives.
Or delegation is a better way ( which adds one extra level of
indirection) ?

Deligation is also fine. It involves a little more typing and there may
be some extra (runtime) overhead, but there is no special reason to
expect there to be. I would have thought that modern compilers would
remove any indirection overhead, but again the only way to know is to
measure it.
some of such inheritance are actually from stl container classes, like
deque and other, where I need to give a range support (like
boost::sub_range ) with a get_range method,
or want to remove some functionality like erase, assign, push_front and
pop_back.

For this sort of situation composition or inheritance are both equally
reasonable *provided* that if you use inheritance you sub-class
privately.

Deriving a class from another purely for practial implementation
related reasons is perfectly reasonable, but again, doing so publicly
should be considered an error. An argument could be made for protected
derivation depending on how it is used, but private is best.


K
 
G

Gianni Mariani

toton said:
Hi,
I want a few of my class to overload from a base class, where the
base class contains common functionality. This is to avoid repetition
of code, and may be reducing amount of code in binary, not to get
polymorphic behavior.

How have you come to the conclusion that you have a performance issue ?

None of them has virtual methods, and are self contained (no
destructor at all) thus do not have a chance to have memory error.
Thus the derived classes has additional functionality, not additional
data.

Now, will the derived class suffers any performance penalty, if I
compare it to a single class which contains all of the functionality.

Impossible to tell. Virtual functions may be faster or slower than non
virtuals. You must test it to know.
Second, if I want to suppress some of the functionality, is it ok to
have a private inheritance and forwarding the functionality which I
need from base class ?
Or delegation is a better way ( which adds one extra level of
indirection) ?

You need to give a concrete code example, I'm not really sure what
you're talking about.
 
S

Salt_Peter

toton said:
Hi,
I want a few of my class to overload from a base class, where the
base class contains common functionality. This is to avoid repetition
of code, and may be reducing amount of code in binary, not to get
polymorphic behavior.

Creating an inheritance scheme without virtual functions does not
prevent repetition of code, it practically garantees having to provide
additional code (when compared to virtual functions).
Also, virtual functions, like pure-virtuals, helps the user of the
class(es) extend the system safely.
None of them has virtual methods, and are self contained (no
destructor at all) thus do not have a chance to have memory error.

Oh yes, they have d~tors.
Thus the derived classes has additional functionality, not additional
data.

There is no reason to have any memory issues with polymorphic classes
by using pointers to base. Except, of couse if you fail to make d~tors
virtual when using base pointers - the compiler generated d~tors aren't
virtual. You can also achieve that without virtual destructors too by
only using boost::shared_ptr (which invokes derived d~tors
automatically using voodoo magic, lol).
Now, will the derived class suffers any performance penalty, if I
compare it to a single class which contains all of the functionality.

Since you'll probably be making expensive (and potentially unsafe)
calls to dynamic casts, yes, there certainly may be a performance
penalty.
Second, if I want to suppress some of the functionality, is it ok to
have a private inheritance and forwarding the functionality which I
need from base class ?
Or delegation is a better way ( which adds one extra level of
indirection) ?

private inheritance is actually a form of composition.
some of such inheritance are actually from stl container classes, like
deque and other, where I need to give a range support (like
boost::sub_range ) with a get_range method,
or want to remove some functionality like erase, assign, push_front and
pop_back.

Then you might consider creating the new container with an stl
container as a private member.
And if you do it correctly, you can provide just about anything you
need in the interface, including iterators. Note that std::deque has a
range-checked accessor: at() which throws std::range_error when
violated.

Look for the example posted here using a std::vector:
http://groups.google.ca/group/comp.lang.c++/browse_thread/thread/0997214767b87a9b

Note: that could have been:

template< typename T >
class V : private std::vector< T > // composition, no problem
{
...
};

V in_terms_of a std::vector
 
T

toton

Salt_Peter said:
Creating an inheritance scheme without virtual functions does not
prevent repetition of code, it practically garantees having to provide
additional code (when compared to virtual functions).
Also, virtual functions, like pure-virtuals, helps the user of the
class(es) extend the system safely.


Oh yes, they have d~tors.
Yes, they have. What I mean is the destructor is a blank one (i.e
machine generated)
There is no reason to have any memory issues with polymorphic classes
by using pointers to base. Except, of couse if you fail to make d~tors
virtual when using base pointers - the compiler generated d~tors aren't
virtual. You can also achieve that without virtual destructors too by
only using boost::shared_ptr (which invokes derived d~tors
automatically using voodoo magic, lol).
Shared ptr is not needed, as I don't have any additional data in the
derived class.
Since you'll probably be making expensive (and potentially unsafe)
calls to dynamic casts, yes, there certainly may be a performance
penalty.
I have already said, this inheritance is not for polymorphic behavior,
thus casting is out of question.
private inheritance is actually a form of composition.


Then you might consider creating the new container with an stl
container as a private member.
And if you do it correctly, you can provide just about anything you
need in the interface, including iterators. Note that std::deque has a
range-checked accessor: at() which throws std::range_error when
violated.
Private inheritance may be different from composition , both
conceptually and style wise.
composition needs a delegation, which may or may not get removed, as it
is just a pattern not a language construct.
private inheritance is a language construct, thus very likely it wont
have the level of indirection at the first place.
I also had posted a same type of question some times back. From the
discussion, it looked like inheriting (nonvirtual public inheritance )
is a better way than composition, when one is adding functionality over
the base class (like I am adding range functionality over the deque
class), and not using them polymorphically.
The amount of code to be written, and the level of indirection, esp for
a large class is huge.
Note: that could have been:

template< typename T >
class V : private std::vector< T > // composition, no problem
{
...
};

V in_terms_of a std::vector
And my question is little mis-understood bye you.
My question is, will it have any performance problem (both in terms of
speed and size) compared to the whole thing written as a single class.
Just to give a example, I am adding a few functionality like this
template<typename T>
class range_vector : public boost::circular_buffer<T>{
public:
typedef boost::sub_range<range_vector> range;
typedef boost::sub_range<const range_vector> const_range;
typedef typename boost::circular_buffer<T>::size_type size_type;
using boost::circular_buffer<T>::begin;
range_vector(size_type capacity) :
boost::circular_buffer<T>(capacity){}
range get_range(size_type from,size_type to){
return boost::make_iterator_range(begin()+from,begin()+to);
}
const_range get_range(size_type from,size_type to)const{
return boost::make_iterator_range(begin()+from,begin()+to);
}
};
Will it have same performance as of the original circular_buffer
implementation with this added functionality (i.e if I copy paste this
code to the circular_buffer class).
similarly sometimes I need to suppress few functionality like erase,
assign and others.
Here virtual, polymorphic and nothing like that short of oop concepts
are of importance.
thanks
abir
 
T

toton

Gianni said:
How have you come to the conclusion that you have a performance issue ?
I hadn't came to any conclusion. I am just asking.
Impossible to tell. Virtual functions may be faster or slower than non
virtuals. You must test it to know.
I hadn't said anything like that. What I am saying is, my class is not
for polymorphic use, and thus doesn't contain any virtual function.
What is the reason for virtual method be faster than non-virtual one,
if identical condition is provided ?
testing can lead to a wrong result if not conducted accurately.
Moreover a small test may not do proper judgment for a compiler.
You need to give a concrete code example, I'm not really sure what
you're talking about.
Ok. Here are the examples,
1) adding functionality of ranges to a circular_buffer
template<typename T>
class range_vector : public boost::circular_buffer<T>{
public:
typedef boost::sub_range<range_vector> range;
typedef boost::sub_range<const range_vector> const_range;
typedef typename boost::circular_buffer<T>::size_type size_type;
using boost::circular_buffer<T>::begin;
range_vector(size_type capacity) :
boost::circular_buffer<T>(capacity){}
range get_range(size_type from,size_type to){
return boost::make_iterator_range(begin()+from,begin()+to);
}
const_range get_range(size_type from,size_type to)const{
return boost::make_iterator_range(begin()+from,begin()+to);
}
};
typedef range_vector<int> rvi;
int main() {
rvi v(9);
int x[] = {0,1,2,3,4,5,6,7,8};
v.insert(v.end(),x,x+9);
rvi::range r1(v.get_range(1,5));
}
2) removing functionality like push_front, pop_back, assign, erase ( I
implemented it as private inheritance here, instead of composition)
class queue : private std::deque<T,Alloc>{
public:
queue() : std::deque<T,Alloc>(){}
using std::deque<T,Alloc>::push_back;
using std::deque<T,Alloc>::pop_front;
using std::deque<T,Alloc>::begin;
using std::deque<T,Alloc>::end;
};
int main() {
queue<int> q;
q.push_back(1);
q.push_back(2);
q.push_back(3);
q.pop_front();
//q.push_front(1); can't be done now.
std::copy(q.begin(),q.end(),std::eek:stream_iterator<int>(std::cout,"
"));
const queue<int>& qr = q;
std::copy(qr.begin(),qr.end(),std::eek:stream_iterator<int>(std::cout,"
"));
}
My question is,
are these two examples are same as like original containers with this
functionality (or lack of functionality) or not.
And for second case, composition is better or private inheritance
(Though now I feel that private inheritance better than "artificial"
composition, as it is supported by the language and much cleaner way of
doing).
thanks
abir
 

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

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top