473,394 Members | 1,944 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

non-virtual overloading and performance issue

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
5 1957

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
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

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

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

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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: lothar | last post by:
re: 4.2.1 Regular Expression Syntax http://docs.python.org/lib/re-syntax.html *?, +?, ?? Adding "?" after the qualifier makes it perform the match in non-greedy or minimal fashion; as few...
17
by: cheeser | last post by:
Hello all, Please see the question in the code below... Thanks! Dave #include <iostream>
5
by: klaus triendl | last post by:
hi, recently i discovered a memory leak in our code; after some investigation i could reduce it to the following problem: return objects of functions are handled as temporary objects, hence...
25
by: Yves Glodt | last post by:
Hello, if I do this: for row in sqlsth: ________pkcolumns.append(row.strip()) ________etc without a prior:
14
by: Patrick Kowalzick | last post by:
Dear all, I have an existing piece of code with a struct with some PODs. struct A { int x; int y; };
2
by: Ian825 | last post by:
I need help writing a function for a program that is based upon the various operations of a matrix and I keep getting a "non-aggregate type" error. My guess is that I need to dereference my...
0
by: amitvps | last post by:
Secure Socket Layer is very important and useful for any web application but it brings some problems too with itself. Handling navigation between secure and non-secure pages is one of the cumbersome...
399
by: =?UTF-8?B?Ik1hcnRpbiB2LiBMw7Z3aXMi?= | last post by:
PEP 1 specifies that PEP authors need to collect feedback from the community. As the author of PEP 3131, I'd like to encourage comments to the PEP included below, either here (comp.lang.python), or...
9
by: Francois Grieu | last post by:
When running the following code under MinGW, I get realloc(p,0) returned NULL Is that a non-conformance? TIA, Francois Grieu #include <stdio.h> #include <stdlib.h>
12
by: puzzlecracker | last post by:
is it even possible or/and there is a better alternative to accept input in a nonblocking manner?
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.