C++ ——继承

体现的是代码复用的思想

1、子类继承父类,子类就拥有了父类的特性(成员方法和成员属性)

2、已存在的类被称为"基类"或者"父类"或者"超类";新创建的类被称为"派生类"或者"子类"

注意:

(1)子类继承了父类,子类就拥有了父类的属性和方法

(2)如果子类重写了父类的同名方法,子类对象默认调用的是子类自己的成员方法,如果想调用父类的同名方法,要添加父类作用域限定符

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Father{
复制代码
public:
复制代码
    int num1=88;
复制代码
    int num2=99;
复制代码
public:
复制代码
    //成员方法
复制代码
    void show()const{
复制代码
        cout<<"num1="<<num1<<",num2="<<num2<<endl;
复制代码
    }
复制代码
    void cook(){
复制代码
        cout<<"做水煮鱼"<<endl;
复制代码
    }
复制代码
};
复制代码
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
复制代码
public:
复制代码
    void sing(){
复制代码
        cout<<"唱歌"<<endl;
复制代码
    }
复制代码
    void cook(){
复制代码
        cout<<"做红烧肉"<<endl;
复制代码
    }
复制代码
};
复制代码
int main(){
复制代码
    Son s1;
复制代码
    s1.cook();  //默认子类调用的是自己的成员方法
复制代码
    s1.show();
复制代码
    s1.sing();
复制代码
    s1.Father::cook();  //子类可以使用添加父类作用域限定符,来调用父类的同名方法
复制代码
    return 0;
复制代码
}

1、构造函数

1.1 派生类的构造函数

继承中的无参构造函数

(1)基类(父类)中的构造函数不能被继承

(2)派生类(子类)中必须要调用基类中的构造函数来完成属性的初始化

(3)默认情况下,编译器会自动在派生类中调用父类的无参构造函数

(4)子类继承了父类,子类独有的属性需要在自己的构造函数进行初始化,而子类从父类继承过来的属性,必须通过子类构造函数调用父类构造函数进行初始化

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Father{
复制代码
public:
复制代码
    int num1=88;
复制代码
    int num2=99;
复制代码
public:
复制代码
    //编译器默认的无参构造函数
复制代码
    Father(){}
复制代码
    //有参构造函数
复制代码
    Father(int num1,int num2)
复制代码
        :num1(num1),num2(num2){}
复制代码
};
复制代码
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
复制代码
public:
复制代码
    int a;
复制代码
public:
复制代码
    //编译器默认的子类无参调用父类无参构造函数
复制代码
    Son():Father(){}
复制代码
    //子类有参构造函数调用父类有参构造函数,来完成继承下来的属性的初始化
复制代码
    Son(int num1,int num2,int a):Father(num1,num2),a(a){}
复制代码
};
复制代码
int main(){
复制代码
    Son s2(10,55,66);
复制代码
//    s2.show();
复制代码
    cout<<s2.a<<endl;  //66
复制代码
    return 0;
复制代码
}

1.2 派生类调用基类构造函数

(1)目的:因为构造函数和析构函数,不能继承,所以派生类的构造函数通过调用基类的构造函数完成部分属性的初始化

(2)派生类的构造函数调用基类的构造函数的方式:透传构造、委托构造、继承构造

1.2.1 透传构造

派生类的构造函数直接调用基类的构造函数

复制代码
class Father{
复制代码
public:
复制代码
    int num;
复制代码
public:
复制代码
    //无参构造函数---->委托构造
复制代码
    Father():Father(90){}
复制代码
    //有参构造函数
复制代码
    Father(int num)
复制代码
        :num(num){}
复制代码
};
复制代码
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
复制代码
public:
复制代码
    int num1;
复制代码
public:
复制代码
    //委托构造
复制代码
    Son():Son(2,88){}
复制代码
    //透传构造
复制代码
    Son(int num1,int num):Father(num),num1(num1){}
复制代码
};

1.2.2 委托构造

可维护性好,但效率相对较低

思想:一个类中的构造函数是可以调用这个类中的其他构造函数

父类的无参构造函数调用父类的有参构造函数;子类的无参构造函数调用子类的有参构造函数;子类的有参构造函数透传父类的有参构造函数

注意:委托构造离不开透传构造

复制代码
class Father{
复制代码
public:
复制代码
    int num;
复制代码
public:
复制代码
    //无参构造函数---->委托构造
复制代码
    Father():Father(90){}
复制代码
    //有参构造函数
复制代码
    Father(int num)
复制代码
        :num(num){}
复制代码
};
复制代码
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
复制代码
public:
复制代码
    int num1;
复制代码
public:
复制代码
    //委托构造
复制代码
    Son():Son(2,88){}
复制代码
    //透传构造
复制代码
    Son(int num1,int num):Father(num),num1(num1){}
复制代码
};

1.2.3 继承构造

透传构造的简写方式,一句话自动实现透传构造,编译器会自动给派生类添加n个构造函数(n取决于基类中构造函数的个数),并实现自动透传其基类构造函数

复制代码
class Father{
复制代码
public:
复制代码
    int num;
复制代码
    int age;
复制代码
    string addr;
复制代码
public:
复制代码
    //无参构造函数---->委托构造
复制代码
    Father():Father(90){}
复制代码
    //有参构造函数
复制代码
    Father(int num)
复制代码
        :num(num){}
复制代码
    Father(int age,string addr)
复制代码
        :age(age),addr(addr){}
复制代码
};
复制代码
class Son:public Father{  //public:放在继承的地方,表示继承方式是公有继承
复制代码
public:
复制代码
    int num1=99;
复制代码
public:
复制代码
    //继承构造
复制代码
    using Father::Father;
复制代码
};

2、对象的构建和销毁的过程

(1)成员对象:类中有一个成员,该成员是对象类型,叫做对象成员

先调用成员对象的构造函数,再调用自己的构造函数;析构函数则相反

(2)父子类继承时

先调用父类的构造函数,再调用子类的构造函数;析构函数则相反

(3)静态成员对象:类中有一个静态成员,该成员是一个对象类型

静态成员对象的构造函数先执行,再执行自己的构造函数;析构函数则相反

顺序:

构造函数:静态成员对象---->成员对象---->父类---->子类

析构函数:子类---->父类---->成员对象---->静态成员对象

2.1 成员对象

复制代码
class Demon{
复制代码
public:
复制代码
    //构造函数
复制代码
    Demon(){
复制代码
        cout<<"成员对象的构造函数"<<endl;
复制代码
    }
复制代码
    ~Demon(){
复制代码
        cout<<"成员对象的析构函数"<<endl;
复制代码
    }
复制代码
};
复制代码
class Test{
复制代码
public:
复制代码
    Test(){
复制代码
        cout<<"构造函数"<<endl;
复制代码
    }
复制代码
    ~Test(){
复制代码
        cout<<"析构函数"<<endl;
复制代码
    }
复制代码
};

2.2 父子类继承时

复制代码
class Father{
复制代码
public:
复制代码
    Father(){
复制代码
        cout<<"父类构造"<<endl;
复制代码
    }
复制代码
    ~Father(){
复制代码
        cout<<"父类析构"<<endl;
复制代码
    }
复制代码
};
复制代码
class Son:public Father{
复制代码
public:
复制代码
    Son():Father(){
复制代码
        cout<<"子类构造"<<endl;
复制代码
    }
复制代码
    ~Son(){
复制代码
        cout<<"子类析构"<<endl;
复制代码
    }
复制代码
};

2.3 静态成员对象

复制代码
class P{
复制代码
public:
复制代码
    P(){
复制代码
        cout<<"静态成员对象的构造"<<endl;
复制代码
    }
复制代码
    ~P(){
复制代码
        cout<<"静态成员对象的析构"<<endl;
复制代码
    }
复制代码
};
复制代码
class Phone{
复制代码
public:
复制代码
    //类内声明
复制代码
    static P p1;  //静态成员变量的声明
复制代码
    Phone(){
复制代码
        cout<<"构造函数"<<endl;
复制代码
    }
复制代码
    ~Phone(){
复制代码
        cout<<"析构函数"<<endl;
复制代码
    }
复制代码
};
复制代码
P Phone::p1=P();  //类外初始化

3、权限

3.1 权限修饰符

C++中成员的权限修饰符有3种:

(1)public:共有的 类内、子类内、类外可以访问

(2)private:私有的 只能类内访问

(3)protected:受保护的 类内、子类内可以访问

注意:如果权限修饰符可以省略,默认是private

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Father{
复制代码
public:
复制代码
    int num1;
复制代码
private:
复制代码
    int num2;
复制代码
protected:
复制代码
    int num3;
复制代码
public:
复制代码
    //构造函数
复制代码
    Father(int num1,int num2,int num3)
复制代码
        :num1(num1),num2(num2),num3(num3){}
复制代码
    void show()const{
复制代码
        cout<<this->num1<<" ";  //public 类内可以访问
复制代码
        cout<<this->num2<<" ";  //private 类内可以访问
复制代码
        cout<<this->num3<<" ";  //protected  类内可以访问
复制代码
        cout<<"*******"<<endl;
复制代码
    }
复制代码
};
复制代码
class Son:public Father{
复制代码
public:
复制代码
    using Father::Father;
复制代码
    void fun()const{
复制代码
        cout<<this->num1<<" "<<this->Father::num1<<" ";  //public 子类内可以访问
复制代码
        cout<<this->num3<<" "<<this->Father::num3<<" ";  //protected  子类内可以访问
复制代码
        cout<<"*******"<<endl;
复制代码
    }
复制代码
};
复制代码
int main(){
复制代码
    Father f1(1,2,3);
复制代码
    f1.show();
复制代码
    Son s1(4,5,6);
复制代码
    s1.fun();
复制代码
    cout<<s1.num1<<endl;  //public 类外可以访问
复制代码
    return 0;
复制代码
}

3.2 继承方式

3.2.1 public(共有继承)

(1)父类是public---->子类也是public

(2)父类是protected---->子类也是protected

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Father{
复制代码
public:
复制代码
    int num1;
复制代码
protected:
复制代码
    int num2;
复制代码
private:
复制代码
    int num3;
复制代码
public:
复制代码
    Father(int num1,int num2,int num3)
复制代码
        :num1(num1),num2(num2),num3(num3){}
复制代码
    void fun()const{}
复制代码
    int get_num3()const{
复制代码
        return num3;
复制代码
    }
复制代码
};
复制代码
class Son:public Father{
复制代码
public:
复制代码
    Son(int num1,int num2,int num3)
复制代码
        :Father(num1,num2,num3){}
复制代码
    void show(){
复制代码
        cout<<this->num1<<endl;  //父类public---->子类也是public,类内可以访问
复制代码
        cout<<this->num2<<endl;  //父类protected---->子类也是protected
复制代码
//        cout<<this->num3<<endl;  //报错,父类private---->子类也是private,但是类内不可以直接访问
复制代码
        cout<<this->Father::get_num3()<<endl;  //父类private---->子类也是private,可以间接访问
复制代码
        cout<<"******"<<endl;
复制代码
    }
复制代码
};
复制代码
class Sunzi:public Son{
复制代码
public:
复制代码
    Sunzi(int num1,int num2,int num3)
复制代码
        :Son(num1,num2,num3){}
复制代码
    void fun()const{
复制代码
        cout<<this->num1<<" "<<this->Son::num1<<endl;  //父类public---->子类也是public,派生类内可以访问
复制代码
        cout<<this->num2<<" "<<this->Son::num2<<endl;  //父类protected---->子类也是protected
复制代码
        cout<<"******"<<endl;
复制代码
    }
复制代码
};
复制代码
int main(){
复制代码
    Son s1(1,2,3);
复制代码
    s1.show();
复制代码
    cout<<s1.num1<<endl;  //父类public---->子类也是public,类外可以访问
复制代码
    Sunzi sz(4,5,6);
复制代码
    sz.fun();
复制代码
    return 0;
复制代码
}

3.2.2 protected(受保护的继承)

(1)父类是public---->子类是protected

(2)父类是protected---->子类也是protected

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Father{
复制代码
public:
复制代码
    int num1;
复制代码
protected:
复制代码
    int num2;
复制代码
private:
复制代码
    int num3;
复制代码
public:
复制代码
    Father(int num1,int num2,int num3)
复制代码
        :num1(num1),num2(num2),num3(num3){}
复制代码
    void fun()const{}
复制代码
    int get_num3()const{
复制代码
        return num3;
复制代码
    }
复制代码
};
复制代码
class Son:protected Father{
复制代码
public:
复制代码
    Son(int num1,int num2,int num3)
复制代码
        :Father(num1,num2,num3){}
复制代码
    void show(){
复制代码
        cout<<this->num1<<endl;  //父类public---->子类是protected
复制代码
        cout<<this->num2<<endl;  //父类protected---->子类也是protected
复制代码
//        cout<<this->num3<<endl;  //报错,父类private---->子类也是private,但是类内不可以直接访问
复制代码
        cout<<this->Father::get_num3()<<endl;  //父类private---->子类也是private,可以间接访问
复制代码
        cout<<"******"<<endl;
复制代码
    }
复制代码
};
复制代码
class Sunzi:protected Son{
复制代码
public:
复制代码
    Sunzi(int num1,int num2,int num3)
复制代码
        :Son(num1,num2,num3){}
复制代码
    void fun()const{
复制代码
        cout<<this->num1<<" "<<this->Son::num1<<endl;  //父类public---->子类是protected
复制代码
        cout<<this->num2<<" "<<this->Son::num2<<endl;  //父类protected---->子类也是protected
复制代码
        cout<<"******"<<endl;
复制代码
    }
复制代码
};
复制代码
int main(){
复制代码
    Son s1(1,2,3);
复制代码
    s1.show();
复制代码
    Sunzi sz(4,5,6);
复制代码
    sz.fun();
复制代码
    return 0;
复制代码
}

3.2.3 private(私有继承)

(1)父类是public---->子类是private,类内可以直接访问

(2)父类是protected---->子类是private,类内可以直接访问

(3)父类是private---->子类也是private,但是类内不可以直接访问,可以间接访问

4、多重继承

4.1 概念

继承中,允许有多个基类,每一个基类的继承都可以看作是唯一的独一继承,此时派生类就拥有了所有基类的特性

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
class Sofa{
复制代码
public:
复制代码
    int num=1;
复制代码
public:
复制代码
    void job(){
复制代码
        cout<<"沙发可以坐"<<endl;
复制代码
    }
复制代码
};
复制代码
class Bed{
复制代码
public:
复制代码
    void work(){
复制代码
        cout<<"床可以躺"<<endl;
复制代码
    }
复制代码
};
复制代码
class SofsBed:public Sofa,public Bed{
复制代码
public:
复制代码
    void work(){
复制代码
        cout<<"即可以躺又可以坐"<<endl;
复制代码
    }
复制代码
};
复制代码
int main(){
复制代码
    SofsBed sfb;
复制代码
    sfb.job();
复制代码
    sfb.work();
复制代码
    cout<<sfb.num<<endl;
复制代码
    sfb.Bed::work();
复制代码
    return 0;
复制代码
}

问题:多个基类同时拥有同名成员函数,此时派生类对象直接调用该函数会产生歧义

解决方法:添加基类作用域限定符

4.2 菱形继承

多继承中的若干个基类,又同时拥有同一个基类,此时叫菱形继承(钻石继承)

复制代码
#include <iostream>
复制代码
using namespace std;
复制代码
//爷爷类
复制代码
class Furniture{
复制代码
public:
复制代码
    void show(){
复制代码
        cout<<"我们是家具"<<endl;
复制代码
    }
复制代码
};
复制代码
//基类
复制代码
class Sofa:virtual public Furniture{};
复制代码
class Bed:virtual public Furniture{};
复制代码
//派生类
复制代码
class SofsBed:public Sofa,public Bed{};
复制代码
int main(){
复制代码
    SofsBed sfb;
复制代码
//    sfb.show();  //报错,问题:两个基类拥有了同名函数,产生了歧义
复制代码
    //解决方法1:使用基类作用域限定符
复制代码
    sfb.Bed::show();
复制代码
    sfb.Sofa::show();
复制代码
    //解决方法2:使用虚继承
复制代码
    /*继承方式有两种:普通继承(默认的)和虚继承(继承方式前添加virtual关键字)*/
复制代码
    sfb.show();
复制代码
    return 0;
复制代码
}
相关推荐
Hello.Reader6 分钟前
深入理解 Rust 的 `Rc<T>`:实现多所有权的智能指针
开发语言·后端·rust
程序员阿鹏8 分钟前
jdbc批量插入数据到MySQL
java·开发语言·数据库·mysql·intellij-idea
yoona10209 分钟前
Rust编程语言入门教程(八)所有权 Stack vs Heap
开发语言·后端·rust·区块链·学习方法
莲动渔舟10 分钟前
国产编辑器EverEdit - 在编辑器中对文本进行排序
java·开发语言·编辑器
ChoSeitaku38 分钟前
12.重复内容去重|添加日志|部署服务到Linux上(C++)
linux·c++·windows
挣扎与觉醒中的技术人43 分钟前
网络安全入门持续学习与进阶路径(一)
网络·c++·学习·程序人生·安全·web安全
滴_咕噜咕噜1 小时前
C#基础总结:常用的数据结构
开发语言·数据结构·c#
martian6651 小时前
【Java高级篇】——第16篇:高性能Java应用优化与调优
java·开发语言·jvm
OTWOL1 小时前
【C++编程入门基础(一)】
c++·算法
许苑向上2 小时前
Java八股文(下)
java·开发语言