关于区分接口继承和实现继承
开头,不说,这个程序对于现在基础薄弱的我,实在难得
#include <iostream>
#include <string>
using std::string;
using std::cout;
如标题所言,
class Shape {
public:
virtual void draw() = 0;//pure virtual fcn
virtual void error(const string &msg);//virtual fcn
int objectID()const//non_virtual fcn
{
cout << "Shape->objectID \n" ;//本来向定义在类外,但这个const不知道该怎么办?
cout << " i: " << i << "\n";
i++;
return i;
}
};
类外,定义memeber fcn,我相信这是一个好习惯
void Shape::error(const string &msg)
{
cout << "Shape->error\n";
}
void Shape::draw()//when virtual fcn define that can't plus key word 'virtual'
{
cout << "Shape->draw()\n";//although it is prue virtual fcn, but also is called
}
class Rectangle : public Shape
{
public:
virtual void draw()
{
cout << "Rectangle->draw\n";
}
virtual void errer(const string & msg)
{
cout << "Rectangle->error\n";//over base class
}
virtual void error()
{
cout << "when paras isn't same\n";
}
int objectID()const
{
return Shape::objectID();
}
int objectID()
{
cout << "Rectangle->object";
cout << " i: " << i << std::endl;
i++;
return i;
}
这是主函数
int main()
{
Rectangle r;
r.draw();
Shape *s = &r;
s->draw();//because Shape has no object,and it only using pionter|reffence to derived class object
//so it's dynamic type is all_time devired type
s->Shape::draw();//this is onle way which to call shape's pure virtual fcn
//but premised is the shape's pure virtual fcn has defined
r.errer("Rectangle->errer\n");
//else i think it same sa impure virtual fcn
s->error("Shape->errer\n");
r.objectID();
s->objectID();
system("pause");
return 0;
}
英文可以不看,都是写代码,懒的调输入法了。
effective c++ 书上讲:A纯虚函数就是一个接口,没有实际对象,只提供借口,派生类必须去覆盖借口,这也就说,在你不能确定你之后所有解决的问题对象还不清楚,可以先定义个抽象基类。例如,shape,书上讲,这是一个模拟画图的程序,你根本不知道将来继承它的是椭圆还是矩形,所以这种情况下可以用。
他也有点例外,就是他可以被定义,这有些违背他的本意了,不过总会有特殊情况吗!当他定义时,就像一个默认的定义,派生类可以改写,可以直接使用,且调用时,得显式调用(using shape:: draw()),跟simple virtual fcn
B虚函数,也是一个借口,你应该提供定义,派生类也可以改写,关于谁调用他,我觉得就是之前总结的动态类型,静态类型一说,(这里并没有进行代码检测,还有关键字遮盖也得检测,后面会补上的)
Cnon_virtual fcn ,书上说,既然你决定用这种方式来定义,说明你并不想让继承者来改变你的初衷,但,实在太容已改变了,重载(这里也要研究一下之前的代码,为什么我所见的代码大多都是定义这样的函数)
这里当然有自己的东西。
1,仅仅是const,也算是重载版本
2,virtual 类外定义不加,(总是记不住)
3,就我现在看到的只有draw()是由他动态类型决定的
4,我还尽量让int (),有意义,就是返回调用他的次数,这里如果你不想违背函数的本意,只能在派生类调用base class