基础语法
一个类继承一个类在定义类的后面加上 :权限 类名
比如B继承A
class A{}; class B:public A{};
子类共有/私有/保护继承父类,在子类内只能访问父类的共有/保护成员,私有都不行。只有当子类共有继承父类,子类外可以访问父类的共有成员 其他成员都不行。
class Father
{
public:
int a=1;
private:
int b=1;
protected:
int c=1;
};
class Sun1:public Father
{
public:
void show()
{
a;c;//b不能访问
}
};
class Sun2:private Father
{
public:
void show()
{
a;c;//b不能访问
}
};
class Sun3:protected Father
{
public:
void show()
{
a;c;//b不能访问
}
};
void show()
{
Sun1 a;
a.a;//可以访问
Sun2 b;Sun3 c;//不能访问Father的属性
}
多态引入
一般所有父类出现的地方都可以用子类代替,但是访问不了子类属性。
函数需要父类对象时传入子类对象进去
注意:子类只能是共有继承父类(其他继承方式父类没有宇哥属性能访问)
父类引用引入子类
直接赋值
父类指针指向子类对象
class A{public:int a;}class B:public A{}
void C(const A& a)//没有改变对象值,使用常引用节省空间
{
a.a;//但是不能访问子类的属性
B b;
A& c=b;//父类引用引入子类
A d=b;//直接赋值
A* e=&b;//父类指针指向子类对象
}
子类继承父类不会把父类的构造析构函数继承。
子类创建对象的时先调用父类构造函数,再调用子类构造函数;子类对象删除时先调用子类析构函数,在调用父类析构函数。
如果父类写了构造函数,子类不想写
class A
{
public:
int a;
A(int a=1)//如果B a(3);这个构造类型子类没有,就不会去调用子类构造函数
:a(a){}
};
class B:public A
{
using A::A;//相当于继承父类的构造函数
B(){}
}
继承-静态成员
类中静态成员 是 子类和父类共享的,子类父类都可以改变静态变量
class A
{
public:
inline static int a=0;
A(){a++;}
};
class B:public A
{
using A::A;
B(){a++;}
}
void show()
{
A a[10];
//A::a==10
B b[10];
//A::a==10+20==30
}
当子类有与父类同名的属性时,子类的对象调用那个同名属性默认会去调用子类的属性
子类调用父类函数,此父类函数调的属性有与子类属性同名时,调用的是父类的属性
子类调用子类函数,此子类函数调的属性有与父类属性同名时,调用的是子类的属性
访问同名属性(类内类外都能(访问权限正确情况下)):
父类::相同属性名,或者this->父类名::相同属性名
父类名::相同函数(),或者this->父类名::相同函数()
注:子类有与父类相同名的函数也就是 函数的重定义(覆盖)
多继承
class A
{
public:
int j=0;
};
class A1:public A
{
public:
int a=0;
int b=0;
};
class A2:public A
{
public:
int b=0;
int c=0;
};
class B:public A1,public A2
{
public:
};
void show()
{
//访问形式
B a;
a.a; a.c;
a.A1::b; a.A2::b;
a.A1::j; a.A2::j;
a.A::j;
//不能a.j;
}
B对象为什么不能直接访问j?
因为这种多继承方式下,B类有他的两个父类A1,A2,而A1和A2各含有A类,所以不能直接访问j,所以引入虚继承。
虚继承
把上面一个代码的第6,12行改成
class A1:virtual public A//在public 类名前面加上 virtual就行了
class A2:virtual public A
就能直接访问j了
因为这样B类直接有A、A1、A2,A1和A2保存了指向A的指针,节省空间。