1.类的继承
语法: class 导出类名 : 继承方式 基类名1, ..., 继承方式 基类名n 类体
继承方式有public, protected, private三种.
导出类对象构成:(1)基类的对象; (2)导出类部分.
导出类中成员的访问权限,如下表所示.
继承方式 | 基类private成员 | 基类protected成员 | 基类public成员 |
private | private | private | private |
protected | private | protected | protected |
public | private | protected | public |
测试程序:
#include "stdafx.h"
class Base
{
private:
int b1;
protected:
int b2;
public:
int b3;
};
class D : public Base
{
private:
int d1;
protected:
int d2;
public:
int d3;
};
class E :private D
{
private:
int e1;
protected:
int e2;
public:
int e3;
};
void main()
{
Base b;
//error C2248: 'Base::b1' : cannot access private member declared in class 'Base'
//b.b1 = 1;
//error C2248: 'Base::b2' : cannot access protected member declared in class 'Base'
//b.b2 = 2;
b.b3 = 3;
D d;
//error C2248: 'Base::b1' : cannot access private member declared in class 'Base'
//d.b1 = 1;
//error C2248: 'Base::b2' : cannot access protected member declared in class 'Base
//d.b2 = 2;
d.b3 = 3;
//error C2248: 'D::d1' : cannot access private member declared in class 'D'
//d.d1 = 4;
//error C2248: 'D::d2' : cannot access protected member declared in class 'D'
//d.d2 = 5;
d.d3 = 6;
E e;
//error C2248: 'Base::b1' : cannot access private member declared in class 'Base'
//e.b1 = 1;
//error C2248: 'Base::b2' : cannot access protected member declared in class 'Base'
//e.b2 = 1;
//error C2247: 'Base::b3' not accessible because 'E' uses 'private' to inherit from 'D'
//e.b3 = 1;
//error C2248: 'D::d1' : cannot access private member declared in class 'D'
//e.d1 = 1;
//error C2248: 'D::d2' : cannot access protected member declared in class 'D'
//e.d2 = 1;
//error C2247: 'D::d3' not accessible because 'E' uses 'private' to inherit from 'D'
//e.d3 = 1;
//error C2248: 'E::e1' : cannot access private member declared in class 'E'
//e.e1 = 1;
//error C2248: 'E::e2' : cannot access protected member declared in class 'E'
//e.e2 = 1;
e.e3 = 1;
}
注: 在类的外部只能访问类的public成员.
2.不可继承
(1)构造函数
(2)析构函数
(3)operator =
导出类构造函数定义:
构造函数(形参表):成员初始化表 函数体
成员初始化表: 基类名(实参表), 数据成员名(实参)
{
普通成员赋初值;
}
构造函数调用次序:
先基类(顺序为类继承时的顺序),对象成员(顺序是在类体中声明的顺序).
析构函数调用次序正好相反.
3.虚函数
(1)向上转型
例如:
#include "stdafx.h"
class Base
{
};
class Derived : public Base
{
};
void main()
{
Base b, *p;
Derived d, *q;
p = &b;
//指向基类的指针可以指向子类,反之则不行.
p = &d;
q = &d;
q = (Derived *)&b;
}
注:q = (Derived *)&b;是C语言强制转换用法,C++中应使用新引入的cast运算.
(2)绑定(binding)
由函数调用确定函数体的过程.
静态绑定:编译时绑定;
动态绑定:运行时绑定.
(3)虚函数
定义语法:
virtual 值类型 函数名(形参表) 函数体
注意:
a.在类体外定义时,virtual可不用写
b.在导出类中,override虚函数时,virtual可不写,但函数原型必须相同.
特点:使用指针或者引用调用虚函数时,具体调用哪个函数,由指针所指对象的类型决定.
例子:
#include "stdafx.h"
#include <iostream>
using namespace std;
class Base
{
public:
virtual void f()
{
cout << "f in Base" << endl;
}
void g()
{
cout << "g in Base" << endl;
}
};
class Derived : public Base
{
public:
void f()
{
cout << "f in Derived" << endl;
}
void g()
{
cout << "g in Derived" << endl;
}
};
void main()
{
Base *p = new Derived();
p->f();
p->g();
Base *q = new Base();
q->f();
q->g();
}
(4)纯虚函数:只声明,没有定义的虚函数
声明语法:
virtual 值类型 函数名(形参表) = 0;
抽象类:至少含有一个纯虚函数的类.抽象类不能实例化,即不能定义对象.
#include "stdafx.h"
#include <iostream>
using namespace std;
#include "string.h"
class List;
class Node
{
private:
Node * next;
public:
virtual void show() = 0;
void insert(Node **h)
{
next = *h;
*h = this;
}
friend class List;
};
class iNode : public Node
{
int info;
public:
iNode(int x)
{
info = x;
}
void show()
{
cout << info << " ";
}
};
class sNode : public Node
{
char s[100];
public:
sNode(char *t)
{
strcpy(s, t);
}
void show()
{
cout << s << " ";
}
};
class List
{
Node *head;
public:
List()
{
head = NULL;
}
void ins(Node *p)
{
p->insert(&head);
}
void display()
{
Node *p = head;
while(p)
{
p->show();
p = p->next;
}
}
};
void main()
{
List list;
list.ins(new iNode(1));
list.ins(new iNode(2));
list.ins(new iNode(3));
list.ins(new iNode(4));
list.ins(new iNode(5));
list.ins(new sNode("ABC"));
list.ins(new sNode("b"));
list.ins(new sNode("a"));
list.display();
}
注:虚析构函数的使用略.
<补充>
void insert(Node **h)
{
next = *h;
*h = this;
show();
cout << endl;
}
添加show()方法之后,首先编译不会出错,然后调用的是子类的方法.