• Advertisement
Sign in to follow this  

Inheritance, virtual interface classes, derived classes

This topic is 4519 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Greetings, I hope what I describe next makes sense. I have been given two interface classes (pure virtual/abstract classes). One interface says I must implement functions F(x) and G(x). The other interface says I must implement functions F(x) and H(x). The functionality of F(x) is identical to both classes. My initial thought was to make a base class, Bclass, that implements F(x). I'd then make two derived classes, Dclass1 and Dclass2. Dclass1 would inherit from Bclass, inherit the F(x) function, and implement G(x). Dclass2 would inherit from Bclass, inherit the F(x) function, and implement H(x). Pretty striaght forward and simple. Now, how do I make Dclass1 a derived class of the interface that says I must implement F(x) and G(x)? How do I do the same for Dclass2? Is it possible somehow for Dclass1 to inherit both Bclass and the abstract interface, implement G(x), and have the Bclass implementation of F(x) satisfy the requirement (from the abstract interface class) that Dclass1 implement F(x)? I could make them completely seperate entities, and duplicate the functionality of F(x). However, this code duplication seems undesirable, and I'm thinking there must be a way to avoid it. (Some notes: F(x) represents a lot of funcionality, say, 90% of what Dclass1 and Dclass2 will do, so it would be a lot of code duplication. G(x) and H(x) functionality are completely seperate/independant from each other. In other words, I wouldn't want a single class that implemented everything. They have to be two seperate classes. I have been given the interfaces as abstract classes and do not have the power to change them.)

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by Mantear
Greetings,

I hope what I describe next makes sense.

I have been given two interface classes (pure virtual/abstract classes). One interface says I must implement functions F(x) and G(x). The other interface says I must implement functions F(x) and H(x). The functionality of F(x) is identical to both classes.

...

Now, how do I make Dclass1 a derived class of the interface that says I must implement F(x) and G(x)? How do I do the same for Dclass2? Is it possible somehow for Dclass1 to inherit both Bclass and the abstract interface, implement G(x), and have the Bclass implementation of F(x) satisfy the requirement (from the abstract interface class) that Dclass1 implement F(x)?


To do what you describe here, you'd simply:
#include <iostream>
using std::cout;

class a_interface {
public: virtual void common_method() = 0;
virtual void a_exclusive_method() = 0;
};

class b_interface {
public: virtual void common_method() = 0;
virtual void b_exclusive_method() = 0;
};

template< typename interface >
class common_interface : public interface {
public: void common_method() { cout << "ab common\n";};
};

class a_object : public common_interface< a_interface > {
public: void a_exclusive_method() { cout << "a exclusive\n"; };
};

class b_object : public common_interface< b_interface > {
public: void b_exclusive_method() { cout << "b exclusive\n"; };
};

int main() {

a_object a;
b_object b;

a.common_method();
b.common_method();

// the template parameter interface forces these functions to be
// implemented in classes deriving from common_interface< interface >
a.a_exclusive_method();
b.b_exclusive_method();

return 0;
}


Templates are your friend [smile]. As to whether this is the most optimal solution depends on what objects these interfaces abstract, the extent of which the common method is integrated into them and the specialization of their exclusive methods.

But this should at least give you a place to start from, then profile later.

Share this post


Link to post
Share on other sites
Hmm, I haven't really dug into templates before. I have a C/embedded background, and am doing some C++ work now. Looks like I'll have to read up on templates. Always more to learn!

The reason for my dilema came about because I've been tasked with implementing a new feature. The new feature was designed with C++ in mind. However, we're under a CORBA environment, hence, the abstract interfaces. Neither the CORBA environment nor the design can be changed, so I'm stuck with what I have.

The best way to describe these objects are as Tx and Rx ports for data flow between two different programs. They have a lot in common. Port connections, base CORBA object setup stuff, etc. But their Tx and Rx characteristics, the direction of the data flow and what the ports do to the data in that direction, differ greatly. So my first thought was make a base class, and derive two others that deal specifically with the Tx/Rx. However, the CORBA IDL generated interface/abstract class, which I need to inherit, caused me great headaches. They had interfaces for both the commonly shared functions, as well as the specific Tx and Rx functions.

Share this post


Link to post
Share on other sites
If the classes only need to share code and don't need to be treated as part of the same hierachy then you should consider making a class that implements F() and using either composition or private inheritance.

Share this post


Link to post
Share on other sites
While the actual problem is rather convuluted, I suspect that virtual parents would solve the problem


class b : public virtual common

that will make it's parent actually be a reference thus if you have a class that extends b and another like b, they will both point to the same class common

hope that helps,
Indy

Share this post


Link to post
Share on other sites
Nitage,

I'm not sure what you mean. I haven't heard of composition before, and I don't know how private inheritance would do anything usefull. Could you expand on your thoughts?


Arelius,

Making the base class virtual doesn't solve the problem with the interfaces. My problem can be generalized somewhat. Basically, how would you implement the situation where you have two interfaces/abstract classes that are similar, (that is, they share at least one common/identical function, but have at least one non-common funcion each).

-- What I have --
Interface1: contains pure virtual declarations of F(x) and G(x)
Interface2: contains pure virtual declarations of F(x) and H(x)

-- What I want --
Class1: Contains implementation of F(x) and G(x)
Class2: Contains implementation of F(x) and H(x)

F(x) is identical to both Classes.

If I make a base class for Class1 and Class2 that implements F(x), Class1 and Class2 would implement G(x) and H(x) respectively. However, at what point/how do I inherit the intefaces? If the base class inherits them (remember, they're pure virtuals), the base class would trickle down pure virtual declarations of G(x) and H(x) to both derived classes (which is undesirable). Both Class1 and Class2 would end up needing to implement functions that do not belong in them.


I hope I'm making sense. If I misunderstood either of your statements, please expand on your thoughts. I'm no C++ expert by any stretch and need further explainations.

Share this post


Link to post
Share on other sites
It seems to me that you want these classes to share a function implementation but not to be polymorphically related - they have different interface (base) classes.

You have class Implementation1 which implements class Interface1.
You have class Implementation2 which implements class Interface2.

To use a common F() function in both classes you have several options:


The template option as stylin described.

Use a free function (that is a function which isn't a member function as F() and have Implementation1 and Implementation2 have F functions which call the free F function.

Have a class which implements F() and have Implementation1 and Implementation2 hold a member variable of that type (ths is composition).

Use private inheritance - Implementation1 & Implementation2 inherit publicly from their interfaces and privatley from a class which implements F. This option is probably the worst as it introduces multiple inheritance without really bringing you any benefit.

Share this post


Link to post
Share on other sites
Quote:
Original post by Mantear
If I make a base class for Class1 and Class2 that implements F(x), Class1 and Class2 would implement G(x) and H(x) respectively. However, at what point/how do I inherit the intefaces? If the base class inherits them (remember, they're pure virtuals), the base class would trickle down pure virtual declarations of G(x) and H(x) to both derived classes (which is undesirable). Both Class1 and Class2 would end up needing to implement functions that do not belong in them.


Essentially the template technique above does what you didn't want to do in your first post, ie., make two distinct classes and manually copy the functionality of f(x). If this is the behaviour you desire, then I think this is the easiest and clearest approach.

With composition, only the exclusive interfaces would be exposed, but you'd still have to duplicate the common functionality in both classes, which you wouldn't have to do if you used (virtual) inheritance. Many times you'll inherit based on an 'is-a' relationship, whereas composition is usually a 'has-a' relationship (subtle, but the difference is between "this object is that kind of object" and "this object has an interface to that object").

Share this post


Link to post
Share on other sites
Unfortunately, I do want them to be related. F(x) represents much more than just a simple function. Since I'm using CORBA, everything must be within a class and self contained. If I do something like call another object to perform F, I've just added another set of interfaces. Both Implementaions would require an interface definition that can call that F function, and I'm back where I started.

If you're unfamiliar with CORBA, it's a multi-language multi-platform system that allows you to write a single program over any supported language over any number of computers. You can have one program running on a computer in the U.S. written in C++ call a function that exists on a computer in the U.K. written in Java. A CORBA IDL file defined the interfaces for that function call and generated some C++ and Java headers (my interface/abstract class). As far as the calling C++ routine is concerned, the function is like any other function. CORBA takes care of finding where the function is located, whether it be within the same class, somewhere else on the same PC, over a LAN, or over the Net. A CORBA IDL Interface is translated into a C++ base class with all pure virtual functions. Any time I cross the boundry of the instantiation of a class, I need a new CORBA IDL interface to define that interaction.

In my current situation, I have two CORBA IDLs which call out similar interfaces. I could have a single class which just implements everything, but then I would have a Tx Port which has code/functionallity of an Rx Port as well, which is what I'm trying to avoid.

Share this post


Link to post
Share on other sites
After reading up on templates some and looking closely at what stylin posted, that's exactly what I needed. However, none of the other examples I saw went so far as to use the template type for a base class. That is indeed very powerful, and seems to open the door for many other possibilities. Are there any pitfalls associated with doing this? Any drawbacks?

Share this post


Link to post
Share on other sites
Compared to compile-time polymorphism (using templates as described), equivalent run-time polymorphism (inheritance + virtual functions) code is usually slower due to v-table lookups. Compile-time polymorphism adds (sometimes significant amounts) of code bloat as well, although in your specific case this would be negligible.

Also, since we don't have run-time polymorphism available, you can't reference a derived class with a pointer to the base class (what would the template parameter be?), so instead you must simulate it with parameterized functions:
// your CORBA interfaces:
class Tx_interface {
public: virtual void F() = 0;
virtual void G() = 0;
};

class Rx_interface {
public: virtual void F() = 0;
virtual void H() = 0;
};

#include <iostream>
using std::cout;

// code squished for brevity ...
// templated base class
template< typename interface >
class Xx_interface : public interface {
public:
void F() { cout << "ANYx_object::F()\n"; return; }
};

// derived classes
class Tx_object : public Xx_interface< Tx_interface > {
public:
void G() { cout << "Tx_object::G()\n"; return; }
};
class Rx_object : public Xx_interface< Rx_interface > {
public:
void H() { cout << "Rx_object::H()\n"; return; }
};

// parameterized function that works with Xx_objects
template< class x_object >
void some_function( x_object & x_o ) {
x_o.F();
return;
}

int main() {

// create our x_objects
Tx_object tx_o;
Rx_object rx_o;

// work with our common functionality:
some_function( tx_o );
some_function( rx_o );

return 0;
}

Share this post


Link to post
Share on other sites
In my situation, I don't think I'll ever be needing/using a pointer to the base class. If anything, I may get a generic CORBA object ptr (think of them as void*) to a port, which I will then _narrow to either a Tx Port or an Rx Port. My whole reasoning for using a base class was because the two classes were so similar and I didn't want to write the same code twice. It wasn't so I could use polymorphism. I realize that I end up duplicating the code anyways (basically making two base classes, one of each interface type), but at least this way I don't have two pieces of source code which I would need to keep in sync.

Again, thanks for your solution. The results are very clean and exactly what I was looking for. I never would have thought of using a templated class inheritance.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement