我希望通过避免公共继承将类直接添加到新类中。例如,我有一个类
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;
但是这样我违反了公共继承的 is-a 规则。我的square
不是size
,而有一个 size
。所以我必须写
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
,而应该提供相同的界面(在其自己的部分旁边)。
答案 0 :(得分:3)
为什么您的界面size
?为什么不将它设为shape
或boundedarea
或其他类似的,它也描述了界面,并且对于其中任何一个正方形是-a (形状/ boundedarea)?
答案 1 :(得分:2)
不,没有这种可能性。如果要重用“接口”(此名称在C ++中不正式存在),则必须使用继承。
但在这种情况下,我不认为继承是一个坏主意。
修改强>
从std :: containers继承没有问题。虽然它对我没有意义,但以下代码在Visual Studio 2005上编译:
#include <list>
class myclass : public std::list<int>
{
};
答案 2 :(得分:1)
我觉得你想告诉全世界你的square
实现了一个接口,即size
接口。
通常,C ++中的接口表示为抽象基类(不幸的是,它不会绕过is-a)。解决这个问题的一种方法是使用duck typing。在这种情况下,实现size
在square
上提供的功能,并将调用转发给包含的size
对象。除非您的代码要求将对象转换为size
类型的对象,而不是仅仅要求函数存在,否则这应该可以正常工作。
答案 3 :(得分:0)
广场的大小是其组成部分之一,我认为你不会通过继承来违反任何规则。只要这些组件的行为保持不变(相同的宽度,高度,面积),否则您可能希望在基类中将它们声明为虚拟,以便能够在必要时覆盖它们。
正如Dav所说,如果这个名字对你来说真的很奇怪,你可以找到一个更好的命名约定,但就功能而言,这是你想要的继承,为什么使代码更难以阅读和使用?
您也可以查看此检查this documentation on inheritance以说服您使用类似的示例。
答案 4 :(得分:0)
听起来你需要一个名为'sizeable'的'界面'。您可以在其中定义要实现的方形和其他相当大的对象的方法。由于计算将根据形状类型而有所不同,我认为使用实现已经定义了一个大小对象是不合理的。
如果您希望通过其方法植入保持尺寸为对象,也可以按照原始帖子中的说明使用合成。您仍然可能希望将size对象更改为square_size,就像这样。命名法也与有关系有关。
答案 5 :(得分:0)
为什么不编写课程?让square
有一个size
ivar,当您在getArea()
课程上致电square
时,只需在内部调用its_size.getArea()
并返回该值
答案 6 :(得分:0)
这里使用继承违反了Liskov替换原则,所以我会使用合成。
为了访问组合类,如果类很小(只有少量函数,如size
),我会为其成员函数定义包装器,或者将getter / setter用于整个组合对象如果班级很大。