继承与派生
1.各种派生类的比较
基类 | 公有成员 | 私有成员 | 保护成员 |
---|---|---|---|
公有派生类 | 公有成员 | 不可访问成员 | 保护成员 |
私有派生类 | 私有成员 | 不可访问成员 | 私有成员 |
保护派生类 | 保护成员 | 不可访问成员 | 保护成员 |
2.同名成员的访问方式
class Base
{
protected:
int v1;
public:
int v2;
Base(int a=0;int b=0)
{
v1=a;v2=b;
}
};
class Derived:public Base
{
int v2;
public:
int v3;
Derived(int a=0,int b=0)
{
v2=a;v3=b;
}
void func()
{
//使用的是Derived中的v2
int sum1=v1+v2+v3;
//使用的是Base中的v2
int sum2=v1+Base::v2+v3;
}
}
3.赋值兼容原则
派生类对象可以赋值给基类对象,反过来会出现编译错误
class animal
{
public:
void eat()
{
cout<<"animal is eating"<<endl;
}
};
class dog:public animal
{
public:
void eat()
{
cout<<"wang wang"<<endl;
}
};
int main()
{
animal a;
dog d;
d.eat();//输出"wang wang"
a=d;//赋值成功,因为所有的狗都是动物,反过来则会出现编译错误
a.eat();//"animal is eating"
animal &ref_a=d;
ref_a.eat();//"animai is eating"
animal *pointer_a=&d;
pointer_a->eat();//"animal is eating"
return 0;
}
4.单继承下的构造函数与析构函数
class Circle
{
Point center;//包含Point类的对象
float radius;
public:
Circle(float x,float y,float r):center(x,y)
{
radius=r;
}
};
class ColorCorcle:public Circle
{
int color;
public:
ColorCircle(float x,float y,float r,int clolor):Circle(x,y,r)
{
this->color=color;
}
};
- 构造函数与析构函数的调用顺序正好相反
5.多继承派生类
(缺省的继承方式是private)
访问不同基类同名成员时的二义性
class A
{
public:void f(){};
};
class B
{
public:void f(){};
void g(){};
};
class C:public A,public B
{
public:g(){};
};
int main()
{
C C1;
C1.A::f();//通过类名对成员加以限定
C1.B::f();
}
虚基类的使用
引入虚基类的目的是为了解决二义性问题,使公共基类在其派生类对象中只产生一个基类子对象
class A{};
class B1:virtual public A{};
class B2:virtual public A{};
class C:public B1,public B2{};
虚基类构造函数的调用顺序如下:
- 虚基类的构造函数在非虚基类之前调用
- 若在同一层次中包含多个虚基类,那么虚基类构造函数按它们说明的次序调用
- 若虚基类由非虚基类派生,则遵守先调用基类构造函数,再调用派生类构造函数的规则