我们有这样一个定时器
class Timer{
public:
explict Timer(int tickFrequency);
virtual void onTick() const;
...
};
然后比较了继承和复合。
继承的代码:
class Widget:private Timer{
private:
virtual void onTick() const;
...
};
然后书上说:
首先,你或许会想设计Widget使它得以拥有derived classes,但同时你可能会想阻止derived classes重新定义onTick。如果Widget继承自Timer,上面的想法就不可能实现,即使是private继承也不可能。
首先,这里说的是重新定义。重定义函数要求基类中的对应函数是非虚的,而给出的代码是虚的。如果说的是重写,我们不想基类中的对应函数被重写就不要讲它声明为virtual不就可以了吗,书上到底想要说的是一个什么问题???
阿神2017-04-17 15:34:45
이것이 바로 우리가 찾고 있는 것입니다. Timer 개체는 필요한 빈도로 틱하도록 구성할 수 있으며 각 틱마다 가상 함수를 호출할 수 있습니다. 재정의 위젯 세계의 현재 상태를 검사하는 가상 기능입니다.
Timer의 이전 설명에 따르면, Timer의 파생 클래스가 onTick을 재정의하여(예: 새 Timer를 정의할 때) 이 함수의 동작을 변경해야 하기 때문에 onTick이 가상 함수여야 함을 알 수 있습니다. 재정의(redefine)는 다시 쓴다는 뜻이다.
이제 위젯에 타이머가 필요하므로 필요에 맞게 타이머의 onTick 함수를 다시 작성해야 할 수도 있습니다. 동시에 위젯에서 파생된 클래스는 onTick 동작을 변경할 수 없어야 합니다.
위젯이 onTick을 "소유"하도록 하는 두 가지 옵션은 상속 또는 집계입니다.
Widget이 Timer를 상속하는 경우 onTick을 재정의할 수 있지만 이 경우 Widget이 Timer를 상속하고 onTick이 Timer에서 가상 함수로 선언되기 때문에 Widget의 파생 클래스도 onTick을 재정의할 수 있습니다. (간접 기본 클래스에 선언된 가상 함수도 재정의할 수 있습니다. 파생 클래스는 기본 클래스에 선언된 가상 함수를 취소할 수 없습니다. 가상 함수 집합은 기본 클래스에서 virtual로 선언하기만 하면 됩니다. )
집계를 사용하면 상속으로 인해 발생하는 이 문제를 피할 수 있습니다. 위젯은 Timer의 파생 클래스를 집계하고 필요에 따라 파생 클래스의 onTick을 재정의합니다. 책에 제공된 예(WidgetTimer에서 onTick을 선언할 때 가상은 중복됨):
으아악관련 없음:
가상 함수는 취소할 수 없지만 필드의 중첩 관계를 사용하여 기본 클래스의 가상 함수를 숨길 수 있습니다. 예를 들어 동일한 이름으로 호출 가능한 개체를 정의합니다. 이러한 방식으로 일부 특정 호출은 가상 멤버 함수 대신 개체를 직접 찾습니다. 하지만 그래도재작성을 막을 수는 없습니다.
으아악