继承的定义:
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的,体现了由简单到复杂的认知过程.
继承的分类:
公有继承:可访问基类的保护和公有,继承下来的父类的各个数据成员和成员函数的 属性不变 。
保护继承:在派生类中基类的公有变成保护,基类的公有成员在派生类外不能访问,它的
权限变为保护的
;
私有继承:基类里面成员的权限变成
私有的
;
注意:不管是哪种继承,在
派生类内部
父类的保护和公有都可以访问,私有不可以访问。
继承的特点和注意事项:
-
作用域 :在继承的方式下子类和父类是两个不同的作用域;
在
派生类里面定义的函数名字和基类的一样,默认访问派生类的,
访问基类,则要加作用域限定符号(基类::基类成员);不要定义同名函数);
class A
{
public:
int _a;
void Funtest()
{
cout<<"Funtest(B)"<<endl;
}
};
class B:public A
{
public:
int _a;
void Funtest()
{
cout<<"Funtest(A)"<<endl;
}
};
void Funtest()
{
B b;
b.A::_a=1;//
b._a=2;//
b.Funtest();//打印结果为Funtest(B)
}
2.初始化列表:若基类没有缺省的构造函数,派生类必须在派生类的构造函数中显示的给出基类名和参数列表,否则编译不会通过(因为系统默认合成的构造函数);
class
A
{
public
:
A()
{}
A(
int
a)
{
cout<<
"A(int a)"
<<endl;
}
};
class
B:
public
A
{
};
void
Funtest()
{
B b;//屏蔽A(),则编译不会通过
}
3.友元函数不能继承,也就是说基类友元不能访问子类私有和保护成员,原因其实很简单,因为继承的是类的成员,但是友元并不是类的成员。
4.赋值兼容规则(public):
(1)子类对象可以赋值给父类对象;
(2)父类对象不能赋值给子类对象;
(3)父类的指针/引用可以指向子类对象;
(4)子类的指针/引用不能指向父类对象。
class
A
{
public
:
int
_a;
};
class
B:
public
A
{
public
:
int
_b;
};
void
Funtest()
{
A a;
B b;
a=b;
//b=a;
}
5.继承与静态成员:
基类定义了static成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子类,都只有一个static成员实例.
6.继承:
单继承:
一个子类仅有一个直接的父类
class
A
{
public
:
int
_a;
};
class
B:
public
A
{
public
:
int
_b;
};
多继承:
一个子类有两个或两个以上直接的父类
定义方式:类名 名字:属性 名字,属性 名字,...
class
A
{
public
:
int
_a;
};
class
B
{
public
:
int
_b;
};
class
C:
public
A,
public
B
{
};
菱形继承(会产生二义性):
class
A
{
public
:
int
_a;
};
class
B1:
public
A
{
public
:
int
_b;
};
class
B2:
public
A
{
public
:
int
_b;
};
class
C:
public
B1,
public
B2
{
public
:
int
_c;
};
void
Funtest()
{
C c;
c._a=10;
}
解决方法:加virtual ,虚继承(在菱形的前两个边加virtual )
class
A
{
public
:
int
_a;
};
class
B1:
virtual
public
A
{
public
:
int
_b;
};
class
B2:
virtual
public
A
{
public
:
int
_b;
};
class
C:
public
B1,
public
B2
{
public
:
int
_c;
};
void
Funtest()
{
C c;
c._a=10;
}
//但是一般不用虚拟继承:解决了数据的,但是却带来了性能上的消耗;
7.没写继承方式,class默认私有,struct默认公有;