c++ 类的继承

一、类的基本概念

c++最重要的特征是代码重用,通过继承机制可以利用已有的数据类型来定义新的数据类型,新的类不仅拥有旧类的成员,还拥有新定义的成员。 一个 B 类继承于A类,或称从类 A 派生类 B。这样的话,类 A 成为基类(父类), 类B成为派生 类(子类)。 派生类中的成员,包含两大部分: 一类是从基类继承过来的,一类是自己增加的成员。 从基类继承过过来的表现其共性,而新增的成员体现了其个性。

继承的优点:减少代码的冗余 提高代码的重用性

二、继承的格式

派生类定义格式:

Class 派生类名 : 继承方式 基类名{

               //派生类新增的数据成员和成员函数

};

三种继承方式: public : 公有继承 private : 私有继承 protected : 保护继承 从继承源上分: 单继承:指每个派生类只直接继承了一个基类的特征 多继承: 指多个基类派生出一个派生类的继承关系,多继承的派生类直接继承了不止一个基 类的特征

派生类访问控制:

 

 三、对象构造和析构的调用原则

继承中的构造和析构 子类对象在创建时会首先调用父类的构造函数 父类构造函 数执行完毕后,才会调用子类的构造函数 当父类构造函数有参数时,需要在子类 初始化列表(参数列表)中显示调用父类构造函数 析构函数调用顺序和构造函数相 反

class A{
public:
A(){
cout << "A 类构造函数!" << endl;
}
~A(){
cout << "A 类析构函数!" << endl;
}
};
class B : public A{
public:
B(){
cout << "B 类构造函数!" << endl;
}
~B(){
cout << "B 类析构函数!" << endl;
}
};
class C : public B{
public:
C(){
cout << "C 类构造函数!" << endl;
}
~C(){
cout << "C 类析构函数!" << endl;
}
};
void test(){
C c;
}

  四、子类中的构造

Son(int a,int b):Base(a),b(b)
{
//this‐>b = b;
}
class Base
{
private:
 int a;
 public:

 Base()
 {
 cout<<"父类的无参构造函数"<<endl;
 }
 Base(int a)
 {
 this‐>a = a;
 cout<<"父类的有参构造函数"<<endl;
 }
 ~Base()
 {
 cout<<"父类中的析构函数"<<endl;
 }
 };
 class Son:public Base
 {
 private:
 int b;
 public:
 Son()
 {
 cout<<"子类的无参构造"<<endl;
 }
 Son(int b)
 {
 this‐>b = b;
 cout<<"子类的有参构造函数int"<<endl;
 }

 //子类必须用 初始化列表 显示的调用父类的有参构造
 //父类名称(参数)
 Son(int a,int b):Base(a)//显示的调用父类的有参构造
 {
 this‐>b = b;
 cout<<"子类的有参构造函数 int int"<<endl;
 }
 ~Son()
 {
 cout<<"子类中的析构函数"<<endl;
 }
 };
 void test01()
 {
 //子类 默认 会调用 父类的无参构造
 //Son ob1(10);

 //子类必须用 初始化列表 显示的调用父类的有参构造
 //父类名称+()
 Son ob2(10,20);

在实现子类构造函数时,使用初始化列表调用父类的构造函数。

五、继承中同名成员的处理方法

当子类成员和父类成员同名时,子类依然从父类继承同名成员 如果子类有成员和 父类同名,子类访问其成员默认访问子类的成员(本作用域,就近原则) 在子类通 过作用域::进行同名成员区分(在派生类中使用基类的同名成员,显示使用类名限定 符)

class Base{
public:
Base():mParam(0){}
void Print(){ cout << mParam << endl; }
public:
int mParam;
};
class Derived : public Base{
public:
Derived():mParam(10){}
void Print(){
//在派生类中使用和基类的同名成员,显示使用类名限定符
cout << Base::mParam << endl;
cout << mParam << endl;
}
//返回基类重名成员
int& getBaseParam(){ return Base::mParam; }
public:
int mParam;
};
int main(){
Derived derived;
//派生类和基类成员属性重名,子类访问成员默认是子类成员
cout << derived.mParam << endl; //10
derived.Print();
//类外如何获得基类重名成员属性
derived.getBaseParam() = 100;
cout << "Base:mParam:" << derived.getBaseParam() << endl;
return EXIT_SUCCESS;
}
注意: 如果重新定义了基类中的重载函数,将会发生什么?
class Base{
public:
void func1(){
cout << "Base::void func1()" << endl;
};
void func1(int param){
cout << "Base::void func1(int param)" << endl;
}
void myfunc(){
cout << "Base::void myfunc()" << endl;
}
};
class Derived1 : public Base{
public:
void myfunc(){
cout << "Derived1::void myfunc()" << endl;
}
};
class Derived2 : public Base{
public:
//改变成员函数的参数列表
void func1(int param1, int param2){
cout << "Derived2::void func1(int param1,int param2)" << en
dl;
};
};
class Derived3 : public Base{
public:
//改变成员函数的返回值
int func1(int param){
cout << "Derived3::int func1(int param)" << endl;
return 0;
}
};
int main(){
Derived1 derived1;
derived1.func1();
derived1.func1(20);
derived1.myfunc();
cout << "-------------" << endl;
Derived2 derived2;
//derived2.func1(); //func1 被隐藏
//derived2.func1(20); //func2 被隐藏
derived2.func1(10,20); //重载 func1 之后,基类的函数被隐藏
derived2.myfunc();
cout << "-------------" << endl;
Derived3 derived3;
//derived3.func1(); 没有重新定义的重载版本被隐藏
derived3.func1(20);
derived3.myfunc();
return EXIT_SUCCESS;
}

1、当 父类和子类 成员变量同名时 在子类就近原则 选择本作用域的子类 成员

2、如果在子类中 必须使用父类中的同名成员 必须加上父类的作用域。 

3、子类可以借助父类的公有方法间接的操作父类的私有数据(不可见的数据)

  • 9
    点赞
  • 65
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值