By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,077 Members | 1,175 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,077 IT Pros & Developers. It's quick & easy.

non-virtual overloading and performance issue

P: n/a
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

Dec 7 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a

toton wrote:
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

Dec 7 '06 #2

P: n/a
toton wrote:
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.
Dec 7 '06 #3

P: n/a

toton wrote:
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.l...97214767b87a9b

Note: that could have been:

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

V in_terms_of a std::vector

Dec 7 '06 #4

P: n/a

Salt_Peter wrote:
toton wrote:
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.
Yes, they have. What I mean is the destructor is a blank one (i.e
machine generated)
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).
Shared ptr is not needed, as I don't have any additional data in the
derived class.

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.
I have already said, this inheritance is not for polymorphic behavior,
thus casting is out of question.

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.
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.
Look for the example posted here using a std::vector:
http://groups.google.ca/group/comp.l...97214767b87a9b
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_vectorrange;
typedef boost::sub_range<const range_vectorconst_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

Dec 8 '06 #5

P: n/a

Gianni Mariani wrote:
toton wrote:
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 ?
I hadn't came to any conclusion. I am just asking.
>
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.
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.

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.
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_vectorrange;
typedef boost::sub_range<const range_vectorconst_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<intrvi;
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<intq;
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::ostream_iterator< int>(std::cout,"
"));
const queue<int>& qr = q;
std::copy(qr.begin(),qr.end(),std::ostream_iterato r<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

Dec 8 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.