Does object have function?

J

Jim Langston

What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not. If the instance has
the method then I want to call it, otherwise not.

It is trivial to create a virtual function for a few functions. But I would
have to add every single function that could be interfaced.

I would just to somehow be able to tell if an instance has a function
available. Consider:

#include <iostream>

class Base {
public:
virtual ~Base() {}
};

class DerivedOne : public Base {
public:
void foo() { }
};

class DerivedTwo : public Base {
public:
void foo() { }
};

class DerivedThree: public Base {
};

int main() {
Base* bps[3];
bps[0] = new DerivedOne();
bps[1] = new DerivedTwo();
bps[2] = new DerivedThree();

for ( auto i = 0; i < 3; ++i ) {
DerivedOne* thisOne = dynamic_cast<DerivedOne*>( bps );
if ( thisOne )
thisOne->foo();
}
}

I would have to dynamic_cast for every class that had a foo() defined to
execute all foos. Is there a way to do what I want?

Jim Langston
 
J

Joshua Maurice

What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not.  If the instance has
the method then I want to call it, otherwise not.

It is trivial to create a virtual function for a few functions.  But I would
have to add every single function that could be interfaced.

I would just to somehow be able to tell if an instance has a function
available.  Consider:

#include <iostream>

class Base {
public:
   virtual ~Base() {}

};

class DerivedOne : public Base {
public:
   void foo() { }

};

class DerivedTwo : public Base {
public:
   void foo() { }

};

class DerivedThree: public Base {

};

int main() {
   Base* bps[3];
   bps[0] = new DerivedOne();
   bps[1] = new DerivedTwo();
   bps[2] = new DerivedThree();

   for ( auto i = 0; i < 3; ++i ) {
      DerivedOne* thisOne = dynamic_cast<DerivedOne*>( bps );
      if ( thisOne )
         thisOne->foo();
   }

}

I would have to dynamic_cast for every class that had a foo() defined to
execute all foos.  Is there a way to do what I want?


In short, no.

The longer answer is that this reeks of bad design, in any programming
language. Casts should be rare in statically type OOP programs, and
the use of casts usually signals a bad design. However, without
knowing your specific problem domain, such as what "foo" is, I am
unable to provide any specific advice - well, besides the advice that
you should read the FAQ.
http://www.parashift.com/c++-faq-lite/proper-inheritance.html
 
R

Rui Maciel

Jim said:
What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not. If the instance
has the method then I want to call it, otherwise not.

It is trivial to create a virtual function for a few functions. But I
would have to add every single function that could be interfaced.

I would just to somehow be able to tell if an instance has a function
available. Consider:

It would be much easier to do something like:

<code>
class Base {
public:
virtual void foo() { //do nothing}
};

class DerivedOne : public Base {
public:
void foo() { //do something }
};

class DerivedTwo : public Base {
public:
void foo() { //do something}
};

class DerivedThree: public Base {
};

int main(void) {
Base* bps[3];
bps[0] = new DerivedOne();
bps[1] = new DerivedTwo();
bps[2] = new DerivedThree();

for ( auto i = 0; i < 3; ++i )
{
thisOne->foo();
}

return 0;
}
</code>


This design also sucks but at least is cleaner and straight forward.


Rui Maciel
 
J

Joshua Maurice

This would work:

class Base {
public:
   virtual ~Base() {}

};

class Fooer {
public:
   virtual void foo() = 0;

};

class DerivedOne : public Base, public Fooer {
public:
   void foo() { cout << "DerivedOne::foo()\n"; }

};

class DerivedTwo : public Base, public Fooer {
public:
   void foo() { cout << "DerivedTwo::foo()\n"; }

};

class DerivedThree: public Base {

};

int main() {
   Base* bps[3];
   bps[0] = new DerivedOne();
   bps[1] = new DerivedTwo();
   bps[2] = new DerivedThree();

   for ( int i = 0; i < 3; ++i ) {
      Fooer* thisOne = dynamic_cast<Fooer*>( bps );
      if ( thisOne )
         thisOne->foo();
   }

}


With this multiple inheritance design, I would guess that you probably
want to virtually inherit from Fooer as well (not done in the above
code).
 
G

Goran Pusic

What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not.  If the instance has
the method then I want to call it, otherwise not.

Are these methods all of same signature (e.g. one "int" param)? If so,
then you can do this:

struct base;

typedef int (*pFunc)(base&, int);

struct base
{
virtual pFunc GetFunc(int whichOne) const = 0;
};

struct derived : public base
{
virtual pFunc GetFunc(int whichOne) const
{
return (7 == whichOne) ? &derived::func : NULL;
}
static int func(base&, int) {/*...*/ return 0; }
};

//and then

void f(base& b)
{
pFunc f = b.GetFunc(7);
if (f)
f(b, 1);
}

(That's +/- the same as Paavo's suggestion with message maps, but you
choose your function signature, and, GetFunc allows you to choose//
refuse giving out pFunc at run-time.)

If your functions are of varying signatures, then I would go for mix-
in inheritance and dynamic_cast is better (Fooer example here). In
fact, I see nothing wrong with Fooer example at all. Inspecting if an
object has a particular interface isn't all that bad, after all.
( Inspecting for a lot of of them, which you seem to be doing,
however, smells a bit bad ;-) ).

Goran.
 
P

Paul N

Jim said:
What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not.  If the instance
has the method then I want to call it, otherwise not.
It is trivial to create a virtual function for a few functions.  But I
would have to add every single function that could be interfaced.
I would just to somehow be able to tell if an instance has a function
available.  Consider:

It would be much easier to do something like:

<code>
class Base {
public:
    virtual void foo() { //do nothing}

};

class DerivedOne : public Base {
public:
   void foo() { //do something }

};

class DerivedTwo : public Base {
public:
   void foo() { //do something}

};

class DerivedThree: public Base {

};

int main(void) {
   Base* bps[3];
   bps[0] = new DerivedOne();
   bps[1] = new DerivedTwo();
   bps[2] = new DerivedThree();

   for ( auto i = 0; i < 3; ++i )
   {
       thisOne->foo();
   }

   return 0;}

</code>

I'm not an expert but I'd recommend this technique as well. Just one
thing to add - if you find yourself adding the same "foo" function to
more than one derived class, consider whether you could introduce it
in a single class and derive the others from it.

Just my two pence...
Paul.
 
J

Joshua Maurice

Virtual inheritance would only be necessary if Fooer had
member-variables. Inheriting interfaces (classes with only pure virtual
functions and no member-variables,) does not require virtual inheritance.

I'm not so sure about this. Let me think about it.

At the very least, if you inherit from such an "interface" class
twice, then you will have two distinct base class sub-objects, and
they will have distinct addresses. (IIRC, the intent of the standard
is that two objects (complete or sub-objects) of the same type should
be distinct objects iff they have distinct addresses. However, I
recall that the wording might have been changed to remove this
requirement. Not sure what the situation is.) I would think that that
is counter-intuitive. I think that a programmer might simply assume
that if he has two distinct Fooer (sub)objects (distinct according to
distinct addresses), then he has two distinct complete objects.
However, such inference would be incorrect without virtual
inheritance.
 
J

Joshua Maurice

The empty base class optimization means that the above is not the case.
A base class that contains no data members need not have a distinct
address.

In any case, virtual inheritance only comes into play if there is a
diamond inheritance pattern, which there is not in this example.

IIRC, there was a thread on exactly this topic in the last year. I
think the discussion revolved around whether it was legal, and how the
wording of the standard was changed in one revision to maybe make it
legal.

Let's take the following case:

struct A {};
struct B : A {};
struct C : A {};
struct D : B, C {};

With my rule that two objects of the same type have the same address
iff they're the same object, then you still are allowed to do empty
base class optimization, just not all of it. Ex:
D * d = new D;
C * c = d;
A * ca = c;
B * b = d;
A * ba = b;

bool cmp_ptr(void* x, void* y) { return x == y; }

In that example, d, b, and ba may all compare equal by cmp_ptr. The
empty base class optimization could legally make B object and the A
base class sub-object of B ccupy the same byte, and it could again
make the D object and B base class sub-object occupy the same might.
It could then do the same for C and C's A. However, it could not do it
again for D and C. If it did that, then B's A and C's A would have the
same address, and that would not be allowed.

At least, one version of the standard read that way, and I think a
different version removed that restriction. Can anyone help me out
here?
 
J

Jim Langston

Jim said:
What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not. If the instance
has the method then I want to call it, otherwise not.
It is trivial to create a virtual function for a few functions. But I
would have to add every single function that could be interfaced.
I would just to somehow be able to tell if an instance has a function
available. Consider:

It would be much easier to do something like:

<code>
class Base {
public:
virtual void foo() { //do nothing}

};

class DerivedOne : public Base {
public:
void foo() { //do something }

};

class DerivedTwo : public Base {
public:
void foo() { //do something}

};

class DerivedThree: public Base {

};

int main(void) {
Base* bps[3];
bps[0] = new DerivedOne();
bps[1] = new DerivedTwo();
bps[2] = new DerivedThree();

for ( auto i = 0; i < 3; ++i )
{
thisOne->foo();
}

return 0;}

</code>

<Quote>
I'm not an expert but I'd recommend this technique as well. Just one
thing to add - if you find yourself adding the same "foo" function to
more than one derived class, consider whether you could introduce it
in a single class and derive the others from it.

Just my two pence...
Paul.
</Quote>

Off topic: I sure wish Microsoft could figure out how to freaking quote
messages right. Tried using Microsft Live Mail and it does the exact same
thing, no '>' character.

On topic: This is actually the way I wound up implementing it, but I'm still
not happy with the design.

My form is derived from the functionality I want which is this:
In my program I have a collection of objects in the world. These objects
can be anything and I derive from a base class so I can put the objects in
the same collection.

Now, any object that has a model should have a functioning display routine.
So I simply iterate through (or choose a specific) object then try to
display it. A function object won't necessarily have a display routine
(unless I add one representing a function somehow. Maybe a big f()).

My intention to hold ambigious data in one container stems from the fact
that these objects will be created by the end user by various means. A
sphere, a function, a ball, a race car, a web address, whatever types can be
created.

Now when I display the user space I want to iterate over these objects and
display any that are displayable.

For this first use it is relatively easy and the solution here works but not
as well as I'd like for my purposes.

In the future I may wish to do other things to objects, if it's a function
to call the function with some parameters (which will probably also be
stored in objects). Then I'll have to add antoehr virtual function to base.
And another. And another. And eventually base will be a humongous class
with thousands of possible calls that can be called on each object.

I would rather be able to simply say:

std::map<std::wstring, jglObject>::iterator it = /*a valid map location*/
(*it).display();

But as it is I can't unless I've created display in base as a virtual
function.

Yes, I am fully aware that this is dangerous for the reason that I presume
..display() is going to display the object in OpenGL in my current window,
but perhaps this is not a model, but soemthing else and .display() just
happens to have the same name and breaks code when I execute it.

This is most likely the reason C++ doesn't do what I want it to do, strong
typing.

In reality doesn't the system know that (*it) points to a jglModel or
jglSphere which both have a .display() function? Without the virtual in
base I have to try to cast to every type that has a .display() to see if it
has it.

I am not sure if there is, currently, a [better] solution to my problem or
not. I am just not happy with the current state of affairs. Unless someone
can suggest a better design that gets rid of this "problem".

Regards,

Jim Langston
 
J

Jim Langston

Pete Becker said:
Sure. But if it's a class that responds to events in a GUI (Windows comes
to mind), there are potentially many tens of thousands of functions, with
a correspondingly large vtable.

Well, yeah, but I don't want to clutter up my base class with things most
objects have no concern about.
 
J

Joshua Maurice

My form is derived from the functionality I want which is this:
In my program I have a collection of objects in the world.  These objects
can be anything and I derive from a base class so I can put the objects in
the same collection.

Now, any object that has a model should have a functioning display routine.
So I simply iterate through (or choose a specific) object then try to
display it.  A function object won't necessarily have a display routine
(unless I add one representing a function somehow.  Maybe a big f()).

My intention to hold ambigious data in one container stems from the fact
that these objects will be created by the end user by various means.  A
sphere, a function, a ball, a race car, a web address, whatever types can be
created.

Now when I display the user space I want to iterate over these objects and
display any that are displayable.

For this first use it is relatively easy and the solution here works but not
as well as I'd like for my purposes.

In the future I may wish to do other things to objects, if it's a function
to call the function with some parameters (which will probably also be
stored in objects).  Then I'll have to add antoehr virtual function to base.
And another.  And another.  And eventually base will be a humongous class
with thousands of possible calls that can be called on each object.

I would rather be able to simply say:

   std::map<std::wstring, jglObject>::iterator it = /*a valid map location*/
   (*it).display();

But as it is I can't unless I've created display in base as a virtual
function.

Yes, I am fully aware that this is dangerous for the reason that I presume
.display() is going to display the object in OpenGL in my current window,
but perhaps this is not a model, but soemthing else and .display() just
happens to have the same name and breaks code when I execute it.

This is most likely the reason C++ doesn't do what I want it to do, strong
typing.

In reality doesn't the system know that (*it) points to a jglModel or
jglSphere which both have a .display() function?  Without the virtual in
base I have to try to cast to every type that has a .display() to see if it
has it.

I am not sure if there is, currently, a [better] solution to my problem or
not.  I am just not happy with the current state of affairs.  Unless someone
can suggest a better design that gets rid of this "problem".

Having a giant grab bag container which holds heterogeneous types sort
of takes a side step around a lot of type safety and general good
design. Perhaps it's a good case in your situation. I still don't
understand enough to give you any specific advice.

However, as others have said, given you want this grab bag container,
multiple virtual inheritance sounds like a good idea. You could have a
pure virtual abstract base class "Displayable" with the proper display
functions. Each most-derived type which will be put in the container
(specifically objects of such types) should also derive from
Displayable if they're displayable, and implement the display
functions. When you iterate over the container to display the objects,
do a dynamic_cast to Displayable and call the appropriate display
functions on that pointer to Displayable.

At the very least, I expect that this would lead to better code style
than having a separate dynamic_cast for each most-derived type in the
main draw loop. Also, by keeping it factored in this way, you might
more easily discover a way in the future to keep your objects around
which is better than your giant grab bag.
 
G

Gert-Jan de Vos

My form is derived from the functionality I want which is this:
In my program I have a collection of objects in the world.  These objects
can be anything and I derive from a base class so I can put the objects in
the same collection.

Now, any object that has a model should have a functioning display routine.
So I simply iterate through (or choose a specific) object then try to
display it.  A function object won't necessarily have a display routine
(unless I add one representing a function somehow.  Maybe a big f()).

The Visitor pattern might be of use here. You base class gets a
virtual void accept(visit& v); Each derived class implements it as
v.accept(*this);

Now you can implement a visitor class for any functionality you need
like display(). The display_visitor would contain a set of overloads:
void accept(ball&);
void accept(sphere&);
// etc..

This exchanges flexibility of adding classes for the flexibility of
adding functionality to a stable set of classes.
 
B

Bo Persson

Daniel said:
The empty base class optimization means that the above is not the
case. A base class that contains no data members need not have a
distinct address.

It does need to have a distinct address from other objects of the same
type. For example, the empty base class optimization is not allowed if
the first member of the derived object is also of the base class'
type. Or there are two base classes of the same type.


Bo Persson
 
B

Bogdan

What I am trying to accomplish: I have a map of polymorphic objects and
these objects may have certain methods defined or not.  If the instance has
the method then I want to call it, otherwise not.

It is trivial to create a virtual function for a few functions.  But I would
have to add every single function that could be interfaced.

I would just to somehow be able to tell if an instance has a function
available.  Consider:

#include <iostream>

class Base {
public:
   virtual ~Base() {}

};

class DerivedOne : public Base {
public:
   void foo() { }

};

class DerivedTwo : public Base {
public:
   void foo() { }

};

class DerivedThree: public Base {

};

int main() {
   Base* bps[3];
   bps[0] = new DerivedOne();
   bps[1] = new DerivedTwo();
   bps[2] = new DerivedThree();

   for ( auto i = 0; i < 3; ++i ) {
      DerivedOne* thisOne = dynamic_cast<DerivedOne*>( bps );
      if ( thisOne )
         thisOne->foo();
   }

}

I would have to dynamic_cast for every class that had a foo() defined to
execute all foos.  Is there a way to do what I want?

Jim Langston


If you need to add some functionality to objects, not classes, why not
use the decorator design pattern? This would imply that the method you
does either nothing or does a specific thing.
 
J

James Kanze

This would work:
class Base {
public:
   virtual ~Base() {}

class Fooer {
public:
   virtual void foo() = 0;

class DerivedOne : public Base, public Fooer {
public:
   void foo() { cout << "DerivedOne::foo()\n"; }

class DerivedTwo : public Base, public Fooer {
public:
   void foo() { cout << "DerivedTwo::foo()\n"; }

class DerivedThree: public Base {

int main() {
   Base* bps[3];
   bps[0] = new DerivedOne();
   bps[1] = new DerivedTwo();
   bps[2] = new DerivedThree();
   for ( int i = 0; i < 3; ++i ) {
      Fooer* thisOne = dynamic_cast<Fooer*>( bps );
      if ( thisOne )
         thisOne->foo();
   }


With this multiple inheritance design, I would guess that you probably
want to virtually inherit from Fooer as well (not done in the above
code).


Why?
 
J

James Kanze

This would work:
class Base {
public:
virtual ~Base() {}
};
class Fooer {
public:
virtual void foo() = 0;
};
class DerivedOne : public Base, public Fooer {
public:
void foo() { cout << "DerivedOne::foo()\n"; }
};
class DerivedTwo : public Base, public Fooer {
public:
void foo() { cout << "DerivedTwo::foo()\n"; }
};
class DerivedThree: public Base {
};
int main() {
Base* bps[3];
bps[0] = new DerivedOne();
bps[1] = new DerivedTwo();
bps[2] = new DerivedThree();
for ( int i = 0; i < 3; ++i ) {
Fooer* thisOne = dynamic_cast<Fooer*>( bps );
if ( thisOne )
thisOne->foo();
}
}

With this multiple inheritance design, I would guess that
you probably want to virtually inherit from Fooer as well
(not done in the above code).

Virtual inheritance would only be necessary if Fooer had
member-variables. Inheriting interfaces (classes with only
pure virtual functions and no member-variables,) does not
require virtual inheritance.

I don't see where member variables have much to do with it. You
don't want more than one instance of Fooer in the final object,
or you will get errors when you do the dynamic_cast (since the
target class will be ambiguous).

You don't need virtual inheritance here, since the hierarchy you
are proposing will never have multiple instances of any of the
base classes, even without it.
 
J

James Kanze

The empty base class optimization means that the above is not
the case. A base class that contains no data members need not
have a distinct address.

First, the empty base class optimization is not required by
a compiler. And a class with virtual functions is never really
empty. Whether the base class has data members or not is
irrelevant when considering whether inheritance should be
virtual or not.
In any case, virtual inheritance only comes into play if there is a
diamond inheritance pattern, which there is not in this example.

That's the critical distinction.
 
J

James Kanze

It does need to have a distinct address from other objects of the same
type. For example, the empty base class optimization is not allowed if
the first member of the derived object is also of the base class'
type. Or there are two base classes of the same type.

That's the way I remember it, although I can't find the actual
wording to this effect off hand.

But whether the actual addresses are the same or not is
irrelevant. If you have something like:

struct B1 { virtual ~B1(); };
struct B2 { virtual ~B2(); };
struct M1 : B2 {};
struct M2 : B2 {};
struct D : B1, M1, M2 {};

B1* p1 = new D;
B2* p2 = dynamic_cast<B2*>(p1);

the cast is required to fail. If the inheritance of B2 is
virtual in M1 and M2, it is required to succeed. Whether empty
base class optimization is present or not.
 
J

Joshua Maurice

First, the empty base class optimization is not required by
a compiler.  And a class with virtual functions is never really
empty.  Whether the base class has data members or not is
irrelevant when considering whether inheritance should be
virtual or not.


That's the critical distinction.

Agreed fully. It's just my hunch that any such "pure abstract"
"interface" class like "Displayable" will tend to be implemented by
many classes in contexts such as the OP. Moreover, if there's multiple
inheritance involved, which sounds like a likely proposition
considering the OP's grab bag container, then it sounds prone to the
situation where a class might inherit from two classes which both
inherit from Displayable. It doesn't make sense to me in terms of
contract substitutability to have anything but virtual inheritance
from Displayable in this case. Obviously, as I've said numerous times,
I do not even have a basic understanding of his design or
requirements, so I'm just throwing all of this out there are non-
binding suggestions, possibilities if you will.
 

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,780
Messages
2,569,607
Members
45,240
Latest member
pashute

Latest Threads

Top