2009-11-06 80 views
1

我想通过避免公共继承直接将类添加到新类中。比如我有一个像公开添加,但继承私有

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; } 
}; 

一类,只是想插上它的功能集成到一个新的类像这样

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

,能写

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

但这种方式我m违反是一个规则的公共继承。我的square不是size has-asize。所以我必须写

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

但现在我原来堵塞size功能直接进入square的想法丢失。我必须写

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; 

或添加一些包装为size getter和setter到square

编辑:我必须补充:size不是注定要有一个虚拟析构函数。我不想使用size,它的后代是多态的。

编辑2:另一个例子:你想写一个类,它提供了与std::list<T>相同的接口,但是提供比简单的自由站立功能更多的功能。标准容器不应被分类,因此您必须添加std::list<T>作为成员,并将std::list<T>的所有公开提供的功能直接包装到您的新课程中。这是很多重复性工作,容易出错。

问:是否有可能性的size接口加入公开square未经size公开继承。我的square不应该是size,但应该提供相同的界面(靠近它自己的部分)。

回答

3

为什么您的界面size?为什么不使它成为shapeboundedarea或其他一些,这也描述了接口,并且对于其中的任何一个,确切地说是-al(shape/boundedarea)?

+0

是的,我认为这是一个命名问题。除非你想在其他地方使用size class – djeidot 2009-11-06 12:44:29

+0

否,它只是一个例子。我不想多态地使用大小。大小的功能应该简单地添加到方块。 – phlipsy 2009-11-06 12:54:48

+0

请考虑我最新的修改。如果我想将std :: list 插入我的课程,会发生什么情况? – phlipsy 2009-11-06 13:27:26

2

不,没有这种可能性。如果你想重用一个“接口”(这个名称在C++中不存在),你必须使用继承。

但在这种情况下,我不认为继承是一个坏主意。

编辑:

有从的std ::容器继承没有问题。虽然它没有任何意义对我来说,下面的代码编译在Visual Studio 2005中:

#include <list> 

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

如果我想将std :: list 插入我的课程,那么这是禁止的。标准集装箱不应被分类 – phlipsy 2009-11-06 13:08:05

+0

其合法。我只是试了一下。看到我编辑的帖子。 – 2009-11-06 13:26:44

+0

这是合法的,但没有打算,因为它们没有虚拟析构函数。指向基类的指针不会被正确删除。 – phlipsy 2009-11-06 13:45:12

1

这听起来我要告诉你的square实现一个接口,即size接口世界。

通常情况下,C++中的一个接口被表示为一个抽象基类(不幸的是,它并没有绕过is-a)。解决这个问题的方法之一是使用duck typing。在这种情况下,请执行sizesquare上提供的功能,并将呼叫转发给包含的size对象。除非您的代码要求对象可以转换为size类型的对象,而不是仅仅要求函数存在,否则应该可以正常工作。

+0

没错。但是如果我必须转发大量的公共职能,我该怎么办?或者如果我想将大小插入许多类中。 – phlipsy 2009-11-06 13:10:24

+0

在这种情况下,我认为实用的答案是直接从'size'继承,或者从一个基类继承,该基类会为您进行转发并包含大小本身。是的,它可能与OO谷物相反,但是OTOH如果你不这样做,最终会在复制/粘贴地狱中结束,并尝试在每个班级复制转发,特别是对于大量的功能。 – 2009-11-06 13:22:50

0

该广场的大小作为其组成部分之一,我不认为你是通过继承违反任何规则。只要这些组件的行为保持不变(相同的宽度,高度,面积),否则您可能需要在基类中声明它们为虚拟的,以便能够在必要时覆盖它们。

正如Dav所说,如果名字确实听起来很奇怪,那么您可以找到一个更好的命名约定,但就功能而言,这就是您想要的继承,为什么让代码更难阅读和使用?

你也可以选择这个检查this documentation on inheritance来说服你一个类似的例子。

0

听起来像你需要一个'界面'被称为'大'。在那里,你可以定义你想要的方法和其他可调整的对象来实现。由于计算将根据形状类型而有所不同,我认为有一个尺寸对象已经用实现定义是没有意义的。

如果您希望使用其方法植入来保持对象的大小,也可以像您在原始帖子中所述那样使用组合。您仍然可能想要将大小对象更改为square_size,就像那样。这种命名也与这种关系有关。

0

为什么不编写你的类?让square有一个size伊娃,当您拨打类的电话时,说getArea(),只需让它在内部呼叫its_size.getArea()并返回该值即可。

+0

由于尺寸很简单,所以只转发5个功能是可以的。但是如果我必须转发15个功能会发生什么?或者,如果我想将大小插入许多对象? – phlipsy 2009-11-06 13:36:47

0

在这里使用继承违反了Liskov替代原则,所以我会用组合。

为了访问组合类,如果类很小(只有一些函数,如size),我会为其成员函数定义包装器,或者如果类使用getter/setter来对整个组合对象使用getter/setter很大。