interface vs behavior

E

er

hi,

here's a rather open ended question. someone will probably ask me for
an example. i do have one, but it's specific to a particular narrow
field. i'll try to think of a more universal example. meanwhile here's
a generic example:

class A{virtual xxx membFun(yyy)=0;}//membFun impl in a derived class
class B{virtual xxx membFun(yyy)=0;}//membFun impl in a derived class

the interface is the same, and sometimes the following makes sense:

template<class T> fun1(cont T&){/*...*/};//T is A or B;

but A and B are slightly different in concept i.e. there is some fun2:

fun2(const A&){/*.../*};//but fun2(const B&) would not make sense.

is the above the right approach i.e. keep A and B separate? i'm quite
aware that we could also do
class Common{virtual xxx membFun(yyy)=0;};
class A:public Common{virtual xxx membFun(yyy)=0;}
class B:public Common{virtual xxx membFun(yyy)=0;}
fun1(const Common&){/*...*/}
fun2(const A&){/*...*/}

but have a feeling the is-a relation is not firmly established...
 
A

Alf P. Steinbach

* er:
hi,

here's a rather open ended question. someone will probably ask me for
an example. i do have one, but it's specific to a particular narrow
field. i'll try to think of a more universal example. meanwhile here's
a generic example:

class A{virtual xxx membFun(yyy)=0;}//membFun impl in a derived class
class B{virtual xxx membFun(yyy)=0;}//membFun impl in a derived class

Assuming xxx and yyy are types, and missing semicolons are typos.

the interface is the same, and sometimes the following makes sense:

template<class T> fun1(cont T&){/*...*/};//T is A or B;

Assuming 'cont' is a typo and really means 'const'.

but A and B are slightly different in concept i.e. there is some fun2:

fun2(const A&){/*.../*};//but fun2(const B&) would not make sense.
OK.


is the above the right approach i.e. keep A and B separate?

Depends on A and B.

i'm quite
aware that we could also do
class Common{virtual xxx membFun(yyy)=0;};
class A:public Common{virtual xxx membFun(yyy)=0;}
class B:public Common{virtual xxx membFun(yyy)=0;}
fun1(const Common&){/*...*/}
fun2(const A&){/*...*/}

but have a feeling the is-a relation is not firmly established...

Generally this will be the most practical approach, because (1) it adds
useful constraints -- the most useful, that you have to think about
what Common really should be, i.e. design, and not just willy-nilly
exploit some commonality between A and B in templated code, and because
(2) it does not force the code to reside in header files.

Depending on how much functionality A and B share, you may implement and
think of Common as a pure interface class that A and B implement (in
which case it's /usually/ a good idea to use virtual inheritance, even
though it's seldom done!), or as several interfaces, and/or as a common
abstract or concrete class.

Anyway, Common should probably have a virtual destructor.

Cheers, & hth.,

- Alf
 
S

SasQ

but have a feeling the is-a relation is not firmly established...

There are other ways to reuse code, not only inheritance.
If you want only to reuse some data OR behaviour, but there
is no relationship between those two classes, which could be
the common INTERFACE of those two classes, you can simply use
AGGREGATION.

Make the class with the data/methods of those two classes, and
place the object of that class in those two.
 

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
474,201
Messages
2,571,049
Members
47,655
Latest member
eizareri

Latest Threads

Top