470,863 Members | 1,152 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,863 developers. It's quick & easy.

ABC w/o virtual functions?

Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.

Thanks,

Joseph

Feb 9 '06 #1
18 1520

Joseph Turian wrote:
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.


An abstract function cannot be virtual so there is one strike against
you.

If you don't define the function virtual the subclass functions will
not be called if you are calling through the parent's pointer.

If you can tell at compile time what is being done and with who you can
use templates but this breaks down if you want runtime and it also
breaks down if you are calling with the parent pointer/reference.

In short, the only way to provide polymorphic behavior is to use
virtual functions. You can pass these objects off as their parent but
that is what they will behave like while being passed off as such.

I think you need to look more closely at your problem space and see if
your solution could be better.

Feb 9 '06 #2
"Joseph Turian" <tu****@gmail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.

Thanks,

Joseph


If the method is virtual or not should not increase the derived class size
at all. Go ahead and try it. Methods themselves generally do not increase
the size of an instance, although a derived class has to be larger than a
base class. In other words, try sizeof of your base and yoru derived, make
it virtual, then try it again.
Feb 9 '06 #3

roberts.n...@gmail.com wrote:
Joseph Turian wrote:
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.


An abstract function cannot be virtual so there is one strike against
you.


I meant the exact opposite of course....abstract functions MUST be
virtual and cannot be otherwise.

Feb 9 '06 #4
GB
Jim Langston wrote:
If the method is virtual or not should not increase the derived class size
at all.


That is typically only true if there were already other virtual members.
If there are no virtual members, making one of them virtual will
typically increase the size of objects of this class by the size of a
pointer, which will point to the v-table for the class. This is
implementation-dependent, but that is how it usually works.

Gregg
Feb 9 '06 #5
* Joseph Turian:
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.


You need at least 1 (that's one) byte per object to identify the derived
class of an object.

If you use virtual functions you'll probably use 4 bytes, unless this is
64-bit, in which case you'll probably use 8 bytes, again, per object.

To make do with just 1 byte type info per object you're limiting the
number of derived classes to 256.

The following (not designed or sanity-checked or refactored, just
typed-in-a-hurry) code shows one idea.

I'm sure you can up with techniques to abstract upwards all that
horrendous boilerplate code in each derived class.
#include <iostream>
#include <ostream>

#include <string>
#include <vector>

typedef unsigned char Byte;

class Base
{
public:
typedef std::string (*PseudoVirtualNameFunc)( Base const& );

protected:
Byte myClassId;

protected:
static std::vector<PseudoVirtualNameFunc> pvnFuncs;

Byte install( PseudoVirtualNameFunc aFunc )
{
pvnFuncs.push_back( aFunc );
return static_cast<Byte>( pvnFuncs.size() - 1 );
}

public:
std::string pseudoVirtualName() const
{
return (*pvnFuncs.at( myClassId ))( *this );
}
};

std::vector<Base::PseudoVirtualNameFunc> Base::pvnFuncs;
class Foo: public Base
{
private:
char myObjectId;

protected:
static std::string pseudoVirtualNameForwarder( Base const& self )
{
return static_cast<Foo const&>( self ).pseudoVirtualName();
}

public:
Foo( char objectId ): myObjectId( objectId )
{
static bool isFirstInstance = true;
static Byte theFooClassId;

if( isFirstInstance )
{
theFooClassId = install( &Foo::pseudoVirtualNameForwarder );
isFirstInstance = false;
}
myClassId = theFooClassId;
}

std::string pseudoVirtualName() const
{
return std::string() + "Foo with object id " + myObjectId;
}
};

int main()
{
Foo const obj( 'X' );
Base const& ref = obj;

std::cout << ref.pseudoVirtualName() << std::endl;
std::cout << "Size of Foo is " << sizeof( Foo ) << " bytes." <<
std::endl;
}
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 9 '06 #6
On 8 Feb 2006 22:29:04 -0800, "Joseph Turian" <tu****@gmail.com>
wrote:
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.

Thanks,

Joseph


The solution may be using templates. It will grow your code but not
your data,should be adequate if you use millions of objects but *not*
if you need them all to derive from the same base class and be called
through that base class.

Zara
Feb 9 '06 #7

"Joseph Turian" <tu****@gmail.com> wrote in message
news:11**********************@g14g2000cwa.googlegr oups.com...
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).


You cannot do what you want without adding some data.

It generally depends on the implementation of your compiler, but
in most cases adding virtual methods to a base doesn't increase
the size of the derivants, if _they_ already have virtual methods
anyway. If none of your classes have virtual methods, then you
probably can't escape using some memory.

If you insist on _not_ using virtual methods, you can add a data
member in your ABC, type of which is function pointer. In the
ABC, add a constructor that takes a function pointer and declare
it as protected. Implement the "polymorphic" method so that it
just passes its arguments to the function pointed to by the pointer.
Derived classes will subsequently call the base class constructor
with an argument that points to their implementation of the method.

- Risto -

Simple example follows (syntax errors left as an exercise :-) :

struct Base
{
void (*f)();
Base( void (*p)() ) : f(p) { }
void DoVirtual( void ) { f(); }
};

struct Bird : public Base
{
static void DoBird() { cout << "Quack! Quack!" << endl; }
Bird() : Base(DoBird) { }
};

struct Fish : public Base
{
static void DoFish() { cout << "<blub> <blub>" << endl; }
Fish() : Base(DoFish) { }
};

int main()
{
Bird donald;
Fish nemo;

donald.DoVirtual(); // Quack! Quack!
nemo.DoVirtual(); // <blub> <blub>

return 0;
};
Feb 9 '06 #8
Actually. I think You can get away from the 1byte requirement by
setting up
the function table with typeid([derivedclass]), as key.

But this is probably the best way to do it.

Feb 9 '06 #9
Sorry about missing quote..
Above is ment as a reply to Alfs post:
You need at least 1 (that's one) byte per object to identify the derived class of an object.
If you use virtual functions you'll probably use 4 bytes, unless this is 64-bit, in which case you'll probably use 8 bytes, again, per object.

To make do with just 1 byte type info per object you're limiting the number of derived classes to 256.

The following (not designed or sanity-checked or refactored, just typed-in-a-hurry) code shows one idea.

I'm sure you can up with techniques to abstract upwards all that

horrendous boilerplate code in each derived class.

Feb 9 '06 #10
* je****@alphacash.se:
Actually. I think You can get away from the 1byte requirement by
setting up the function table with typeid([derivedclass]), as key.


Chicken and egg. There's no magic. "typeid" relies on the class being
polymorphic...

However, one could get away from the 1 byte per object requirement by
using custom allocation so that the type of object could be inferred
from the object's address.

But that would be the proverbial fly massacre by H-bomb, I think.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Feb 9 '06 #11
typeid requires a polymorphic class?? typeid(int) works.
Now there seems to be something I dont know.
Enlighten me please.

pseudocode:
map<typeid,function> functionmap;

baseclass::baseclass()
{
}

derivedclass::derivedclass()
{
functionmap[typeid(this)]=function_to_map;
}
// end pseudo code
You say above would require baseclass to be polymorphic, yet
typeid([int,float,char]) works fine?
Please explain.
/Jesper
PS. who do you quote a post? DS

Feb 9 '06 #12

je****@alphacash.se wrote:
PS. who do you quote a post? DS


Assuming you meant "how" rather than "who", from Google Groups you need
to ignore the "Reply" button at the bottom of the message. Instead
click "Show options" at the top of the message and use the "Reply"
button there.

Gavin Deane

Feb 9 '06 #13
Ahh :-)
Thank you.
/Jesper
Gavin Deane wrote:
je****@alphacash.se wrote:
PS. who do you quote a post? DS


Assuming you meant "how" rather than "who", from Google Groups you need
to ignore the "Reply" button at the bottom of the message. Instead
click "Show options" at the top of the message and use the "Reply"
button there.

Gavin Deane


Feb 9 '06 #14
Doh!
I'm stupid. Sorry..
Accessing the right function would be a little less easy :-)

(would brute force dynamic_cast allow for it to work? And if so, would
it be a
plausible solution? How much would the performance suffer?)
/Jesper

Alf P. Steinbach wrote:
* je****@alphacash.se:
Actually. I think You can get away from the 1byte requirement by
setting up the function table with typeid([derivedclass]), as key.


Chicken and egg. There's no magic. "typeid" relies on the class being
polymorphic...

However, one could get away from the 1 byte per object requirement by
using custom allocation so that the type of object could be inferred
from the object's address.

But that would be the proverbial fly massacre by H-bomb, I think.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?


Feb 9 '06 #15
* je****@alphacash.se:
[top-posting, quoting signature]
Using Google's quoting facilities isn't easy! But please,
don't top-post, and don't quote signatures and other extranous
stuff. Corrected.

* je****@alphacash.se: * Alf P. Steinbach:
* je****@alphacash.se:

Actually. I think You can get away from the 1byte requirement by
setting up the function table with typeid([derivedclass]), as key.
Chicken and egg. There's no magic. "typeid" relies on the class being
polymorphic...

However, one could get away from the 1 byte per object requirement by
using custom allocation so that the type of object could be inferred
from the object's address.

But that would be the proverbial fly massacre by H-bomb, I think.


Doh!
I'm stupid. Sorry..
Accessing the right function would be a little less easy :-)


It would be impossible. When all you have is a pointer or reference
to a non-polymorphic Base object, typeid or dynamic_cast doesn't tell
you which dynamic type it is.

(would brute force dynamic_cast allow for it to work?


Nope.
Cheers,

- Alf
Feb 9 '06 #16
ro**********@gmail.com wrote:
roberts.n...@gmail.com wrote:
Joseph Turian wrote:
Let's say I want to have an abstract base class define a method which
all the subclasses will implement.

However, I cannot use virtual methods (long story short: these objects
are only 24 bytes and I have several million of them).

Is it possible for me to define the method in the ABC interface without
virtuals?
As I said, all the subclasses will provide the method.


An abstract function cannot be virtual so there is one strike against
you.

I meant the exact opposite of course....abstract functions MUST be
virtual and cannot be otherwise.


There is no such concept in C++ as "abstract function". Just so there
is no confusion in the future...

V
--
Please remove capital As from my address when replying by mail
Feb 9 '06 #17

Zara wrote:
The solution may be using templates. It will grow your code but not
your data,should be adequate if you use millions of objects but *not*
if you need them all to derive from the same base class and be called
through that base class.


Could you please explain how to do this using templates?

Thanks,

Joseph

Feb 10 '06 #18
je****@alphacash.se wrote:
typeid requires a polymorphic class?? typeid(int) works.
Now there seems to be something I dont know.


It requires a polymorphic class if you need RTTI.
typeid(int) is statically determined, but typeid(*ptrToBase) isn't.

HTH,
Michiel Salters

Feb 10 '06 #19

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by vijay | last post: by
5 posts views Thread by Ryan Faulkner | last post: by
18 posts views Thread by nenad | last post: by
7 posts views Thread by Aguilar, James | last post: by
25 posts views Thread by Stijn Oude Brunink | last post: by
11 posts views Thread by santosh | last post: by
7 posts views Thread by ashishnh33 | last post: by
14 posts views Thread by v4vijayakumar | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.