开发者

Adding publicly but inheriting private

I want to add a class directly into a new class by avoiding public inheritance. For example I have a class like

class size {
private:
    int width;
    int height;
public:
    void set_width(int w) { width = w; }
    int get_width() { return width; }
    void set_height(int h) { height = h; }
    int get_height() { return height; }
    int get_area() { return width*height; }
};

and simply want to plug in it's functionality into a new class like this

class square : public size { 
    // ...
};

and can write

square s;
s.set_width(10);
s.set_height(20);
cout << "Area of the square: 开发者_运维问答" << s.get_area() << endl;

But this way I'm violating the is-a rule for public inheritance. My square isn't a size it has-a size. So I have to write

class square {
public:
    size its_size;
    // ...
};

But now my original idea of plugging the functionality of size right into square gets lost. I have to write

square s;
s.its_size.set_width(10);
s.its_size.set_height(20);
cout << "Area of the square: " << s.its_size.get_area() << endl;

or add several wrappers for the getters and setters of size into square.

Edit: I have to add: size isn't destined to have a virtual destructor. I don't want to use size and it's descendants polymorphically.

Edit 2: Another example: You want to write a class that provides the same interface as std::list<T> but offers a lot more functionality than a simple free standing function can accomplish. The standard containers shoudn't be subclassed so you have to add a std::list<T> as a member and wrap all publicly provided functions of std::list<T> directly to your new class. That's a lot of repetitive work and error prone.

Question: Is there a possibility to add the interface of size publicly into square without publicly inheriting from size. My square shouldn't be a size but ought to offer the same interface (next to its own parts).


Why is your interface size? Why not make it a shape or a boundedarea or some such, which describes the interface just as well, and for either of which a square definitely is-a (shape/boundedarea)?


No, there is no such possibility. If you want to reuse a "interface" (this name does not exist officially in C++), you must use inheritance.

But in such a case i dont think that inheritance is a bad idea.

EDIT:

There is no problem in inheriting from std:: containers. Although it doesn't make sense to me, the following code compiles on Visual Studio 2005:

#include <list>

class myclass : public std::list<int>
{
};


It sounds to me that you want to tell the world that your square implements an interface, namely the size interface.

Normally, an interface in C++ is represented as an abstract base class (which doesn't get around the is-a, unfortunately). One way that you could work around this here would be to make use of duck typing. In this case, implement the functions that size provides on square and forward the calls to the contained size object. Unless your code requires that the object can be converted into an object of type size instead of just requiring the functions to be present, this should work fine.


The square has a size as one of its components, I don't think you are violating any rule by inheriting. So long as the behaviour of those components remain the same (same width, height, area) otherwise you might want to declare them as virtual in the base class in order to be able to override them if necessary.

As Dav said, if the name does really sound odd to you, you can find a better naming convention, but as far as the functionality is concerned, that's inheritance you want, why make the code more difficult to read and use?

You may also check this check this documentation on inheritance to convince you with a similar example.


Sounds like you need an 'interface' called 'sizeable'. In that you can define those methods that you want square, and other sizable objects, to implement. Since the calculations will differ depending on shape types I don't think it makes sense to have a size object already defined with an implementation.

Composition could also be used as you stated in your original post if you want to keep size an object with its method implantation. You still may want to change the size object to square_size, something like that. The nomenclature works out too with the has-a relationship.


Why not compose your classes? Let square have a size ivar, and when you call, say, getArea() on the square class, just have it internally call its_size.getArea() and return that value.


Using an inheritance here violates the Liskov Substitution Principle, so I would use composition.

In order to access the composed class, I would define wrappers for its member functions if the class is small (has only a few functions, like size), or would use getter/setter to the whole composed object if the class is big.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜