一般用层次分类的方法来描述他们的关系
派生类成员包含两大部分
class 派生类名字:继承方式 基类名{
// 派生类新增的数据成员和成员函数
}
/*
继承方式:
public
protected
private
*/
实例
class Person{
public:
void getName(){
std::cout<<"name:"<<_name<<std::endl;
}
void setName(std::string name){
_name=name;
}
void getAge(){
std::cout<<"age:"<<_age<<std::endl;
}
void setAge(int age){
_age=age;
}
protected:
std::string _name;
int _age;
};
class Student:public Person{
/*
* 继承
* 相当于student类里面也有
* std::string _name;
* int _age;
* */
private:
std::string _stuId;
};
class Teacher:public Person{
private:
std::string _teaId;
};
Student s;
Teacher t;
std::cout<<sizeof(Student)<<std::endl; //72B
std::cout<< sizeof(Person)<<std::endl; //40B
c++的继承方式会影响子类的对外访问属性
public
继承:父类成员在子类保持原有的访问等级
protected
继承:父类中public成员变为protected(其他不变)protected依为protected,private依为private
private
继承:父类成员在子类中变成private成员
速记技巧:
认为安全等级public<protected<private
继承时,比继承方式等级低(小于)的变为继承方式等级,比继承方式等级高(大于等于)的不变
protected和private继承区别
private
成员在子类中存在但不可访问,无论何种继承方式,派生类中都不可以访问基类的private
类型的成员protected
成员在子类中存在可以访问,但子类的对象中不可直接访问class A{
public:
int x;
protected:
int y;
private:
int z;
};
class B:public A{
public:
void fun(){
x; //和继承方式无关
y;//public、protected修饰的成员,在派生类可以发访问
// 报错
z;//private修饰的成员,在派生类不可以访问
}
};
构造函数
先有父类后有子类
析构函数
先销毁子类后销毁父类 和构造相反
class A{
public:
int a;
A(){
std::cout<<"A()"<< std::endl;
}
A(int a){
std::cout<<"A(int a)"<< std::endl;
this->a=a;
}
~A(){
std::cout<<"~A()"<< std::endl;
}
};
class B:public A{
public:
B(){
std::cout<<"B()"<< std::endl;
}
//在派生类中手动调用基类的构造函数
B(int b):A(b){
std::cout<<"B(int b):A(b)"<< std::endl;
}
~B(){
std::cout<<"~B()"<< std::endl;
}
};
int main() {
B b;
/*
A()
B()
~B()
~A()
*/
B a(50);
/*
A(int a)
B(int b):A(b)
~B()
~A()
*/
class A{
public:
int a;
A(){
a = 10;
std::cout<<"A()"<< std::endl;
}
~A(){
std::cout<<"~A()"<< std::endl;
}
};
class B:public A{
public:
int a;
B(){
a=20;
std::cout<<"B()"<< std::endl;
}
~B(){
std::cout<<"~B()"<< std::endl;
}
};
B b;
std::cout<<sizeof b<<std::endl;//8B,说明派生类可以继承基类同名属性
// 那么访问b.a是访问的派生类的成员变量还是基类的成员变量呢?
std::cout<<b.a<<std::endl;//20,同名的时候访问派生类的成员属性
//怎么访问基类中与派生类中成员同名的属性?
std::cout<<b.A::a<<std::endl;//10,同名的时候访问基类的成员属性
总结
virtual
父类函数被隐藏起来class D{
public:
void fun(){
std::cout<<"D"<<std::endl;
}
};
class C:public D{
public:
void fun(){
std::cout<<"C"<<std::endl;
}
};
C c;
c.fun(); //访问的是C的成员函数
c.D::fun();//访问的是D的成员函数
class D{
public:
void fun(){
std::cout<<"D::fun"<<std::endl;
}
};
class C:public D{
public:
void fun(int x){
std::cout<<"C::fun"<<std::endl;
}
};
C c;
c.fun(); //访问不到D类的fun,这样会报错
定义格式
class 类名 : 继承方式1 基类名1,继承方式2 基类名2,...,{
}
class A(){
public:
int a;
};
class B(){
public:
int b;
};
class C:public A,public B{
public:
int c;
}
多继承时很容易产生命名冲突,即使我们很小心地将所有类中的成员变量和成员函数都命名为不同的名字,命名冲突依然有可能发生,比如典型的是菱形继承,如下图所示:
class A{
public:
int a_x;
};
class B:public A{
public:
//int a_x;
int b_x;
};
class C:public A{
public:
//int a_x;
int c_x;
};
class D:public B,public C{
public:
//int a_x;
//int b_x;
//int c_x;
int d_x;
};
D d;
std::cout<<sizeof d<<std::endl; //20
std::cout<<d.a_x<< std::endl; //报错 派生类访问间接基类的成员属性是 不知道是为B还是C的
但是这样没什么意义,还有有多份属性
std::cout<<d.B::a_x<<std::endl;
std::cout<<d.C::a_x<<std::endl;
class A{
public:
int a_x;
};
//virtual 虚继承,D类继承B和C中A的属性是共享的,也就是说D中只有一份 a_x
class B:virtual public A{
};
class C:virtual public A{
};
class D:public B,public C{
};
D d;
// 占用空间不同?后续解释 (virtual搞的鬼)
std::cout<<sizeof(D)<<std::endl; //24
std::cout<< sizeof(A)<<std::endl; //4
class AA{
public:
static int num;
};
int AA::num=100;
class BB:public AA{
};
BB::num=50;
//静态成员不仅被继承而且还是共享
std::cout<<BB::num<<std::endl;//50
std::cout<<AA::num<<std::endl;//50
class AA{
public:
static int num;
};
int AA::num=100;
class BB:public AA{
public:
static int num;
};
int BB::num=100;
BB::num=50;
//派生类隐藏基类静态成员变量
std::cout<<BB::num<<std::endl;//50
std::cout<<AA::num<<std::endl;//100