C++ DAY6

这篇具有很好参考价值的文章主要介绍了C++ DAY6。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、菱形继承

又叫钻石继承,由公共子类派生出多个中间子类,又由多个中间子类派生出汇聚子类,汇聚子类

中间子类得到从公共基类继承下来的多个成员。

                  A       --------公共基类
               /    \
              B      C    ------- 中间子类
               \    /
                  D       --------汇聚子类
#include <iostream>
 
using namespace std;
 
//封装公共基类 家具 类
class Jiaju
{
private:
    string color;
public:
    //无参构造
    Jiaju() {cout << "家具的无参构造函数" << endl;}
 
    //有参构造
    Jiaju(string n):color(n)
    {
        cout << "家具的有参构造函数" << endl;
    }
};
 
//中间子类
//封装 沙发的类
class Sofa:public Jiaju
{
private:
    string sitting;
public:
    //无参构造
    Sofa() {cout << "沙发的无参构造" << endl;}
 
 
    //有参构造函数
    Sofa(string s,string c):Jiaju(c),sitting(s)
    {
        cout << "沙发的有参构造" << endl;
    }
    void display()
    {
        cout << sitting << endl;
    }
};
 
 
//中间子类
//封装 床 类
class Bed:public Jiaju
{
private:
    string sleep;
 
public:
    //无参
    Bed() {cout << "床的无参构造" << endl;}
 
    //有参
    Bed(string s,string c):Jiaju(c),sleep(s)
    {
        cout << "床的有参构造" << endl;
    }
    void display()
    {
        cout << sleep << endl;
    }
};
 
//汇聚子类
//封装 沙发床类  继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:
    int w;
public:
 
    //
    Sofa_Bed(){cout << "沙发床的无参构造" << endl;}
 
    //有参构造
    Sofa_Bed(string sit, string s, int w,string c):Bed(s,c),Sofa(sit,c),w(w)
    {
        cout << "沙发床的有参构造" << endl;
    }
};
 
int main()
{
//    Sofa_Bed s;
    Sofa_Bed s1("可坐","可躺",123,"pink");
 
    return 0;
}

由于汇聚子类会得到中间子类从公共基类继承下来的多份基类成员,故引出了虚继承的概念

二、虚继承

为了使汇聚子类只保存一份中间子类从公共基类继承的成员,使用了在中间子类继承方式前virtual

class 类名 : virtual 继承方式 类名   //中间子类
{
    中间子类的拓展;
};

1.默认调用公共基类的无参构造函数

当你创建一个汇聚子类的对象时,编译器需要确定如何初始化公共基类。由于虚继承,公共基类只有一个实例,因此需要明确哪个构造函数应该被调用。

如果你没有在汇聚子类的构造函数初始化列表中显式调用公共基类的构造函数,编译器会默认调用公共基类的无参构造函数。这是因为编译器不知道应该选择哪个中间子类的构造函数来初始化公共基类,所以它选择最安全的选项,即调用无参构造函数。

2.显式调用公共基类的构造函数

如果你想在创建汇聚子类的对象时初始化公共基类的数据成员,你需要在汇聚子类的构造函数初始化列表中显式调用公共基类的构造函数。

这样做可以确保公共基类按照你的需求进行初始化,而不是使用默认的无参构造函数。

#include <iostream>

using namespace std;

//封装公共基类 家具 类
class Jiaju
{
private:
    string color;
public:
    //无参构造
    Jiaju() {cout << "家具的无参构造函数" << endl;}

    //有参构造
    Jiaju(string n):color(n)
    {
        cout << "家具的有参构造函数" << endl;
    }
};

//中间子类
//封装 沙发的类
class Sofa:virtual public Jiaju  //中间子类虚继承公共基类
{
private:
    string sitting;
public:
    //无参构造
    Sofa() {cout << "沙发的无参构造" << endl;}

    //有参构造函数
    Sofa(string s,string c):Jiaju(c),sitting(s)
    {
        cout << "沙发的有参构造" << endl;
    }
    void display()
    {
        cout << sitting << endl;
    }
};

//中间子类
//封装 床 类
class Bed:virtual public Jiaju  //中间子类虚继承公共基类
{
private:
    string sleep;

public:
    //无参
    Bed() {cout << "床的无参构造" << endl;}

    //有参
    Bed(string s,string c):Jiaju(c),sleep(s)
    {
        cout << "床的有参构造" << endl;
    }
    void display()
    {
        cout << sleep << endl;
    }
};

//汇聚子类
//封装 沙发床类  继承于沙发 和 床
class Sofa_Bed:public Bed,public Sofa
{
private:
    int w;
public:
    //
    Sofa_Bed(){cout << "沙发床的无参构造" << endl;}

    //有参构造
    Sofa_Bed(string sit, string s, int w,string c):Jiaju(c),Bed(s,c),Sofa(sit,c),w(w) //需要在汇聚子类中显性调用公共基类的有参构造函数
    {
        cout << "沙发床的有参构造" << endl;
    }
};

int main()
{
//    Sofa_Bed s;
    Sofa_Bed s1("可坐","可躺",123,"pink");
    return 0;
}

C++ DAY6,c++,java,jvm

 三、多态

类的三大属性:继承、封装和多态

 函数重载是静态多态(编译时多态),函数重写是动态多态(运行时多态)

父类的指针或者引用,指向或初始化子类的对象,调用子类对父类重写的函数,进而展开子类的功能。

 函数重写

1> 必须有继承关系

2> 子类和父类有同名同类型的函数

3> 父类中的该函数必须是虚函数

————虚函数指在函数前加上virtual,虚函数满足继承(父类中该函数是虚函数),继承到子类中,该函数依旧是虚函数,如果之后继续继承,继承出的函数仍是虚函数

#include <iostream>
 
using namespace std;
 
// 封装 周 这个类
class Zhou
{
private:
    string name;
    int age;
public:
    //无参构造
    Zhou() {}
 
 
    //有参构造函数
    Zhou(string n, int a):name(n),age(a)
    {}
 
 
    //
    virtual void speek()  //表示该函数是虚函数
    {
        cout << "阿巴阿巴。。" << endl;
    }
};
 
 
//封装 周老师  类,继承于周类
class Teacher:public Zhou
{
private:
    int id;
 
 
public:
    //无参构造
    Teacher() {}
 
 
    //有参构造
    Teacher(string n, int a, int d):Zhou(n,a),id(d)
    {}
 
 
    //
    void speek()
    {
        cout << "看我,上多态,认真听讲" << endl;
    }
};
 
 
//封装 游戏玩家 类 继承于Zhou类
class Player:public Zhou
{
private:
    string game;
public:
    //。。
    Player() {}
 
 
    //有参构造
    Player(string name, int age, string g):Zhou(name,age),game(g)
    {}
 
 
    //
    void speek()
    {
        cout << "稳住,我们能赢" << endl;
    }
};
 
 
int main()
{
    Teacher t("zhangsan",34,1001);
    Zhou *p; //父类的指针
    p = &t;  //父类的指针,指向子类对象  相当于承当老师这个角色
    p->speek();   // 上课
 
 
    Player g("lisi",45,"王者");
 
    p = &g; //此时是游戏玩家这个角色
    p->speek();
 
 
    return 0;
}

赋值兼容规则

只适用于公有继承。对于保护或私有继承,这些规则不适用。

C++ DAY6,c++,java,jvm

  • 类中有虚函数时,类里就会有一个虚指针,虚指针也满足继承
  • 虚指针在类的最前面,虚指针指向了一个虚函数表,虚函数表里记录了虚函数,包括子类对父类重写的函数。
  • 虚指针和虚函数表是实现多态的重要机制。

虚析构函数

虚析构函数用来解决父类指针指向子类时,父类指针释放,导致子类自拓展的空间没有得到释放

#include <iostream>
 
using namespace std;
 
//封装 人 类
class Person
{
private:
    string name;
public:
    //
    Person() {}
 
    //有参构造函数
    Person(string n):name(n)
    {
    }
 
    virtual ~Person()  //虚析构函数  满足继承
    {
        cout << "Person::析构函数"  << endl;
    }
};
 
//封装 学生  继承于人
class Stu:public Person
{
private:
    int id;
public:
    //
    Stu(){}
 
    //有参构造
    Stu(string n , int i):Person(n),id(i)
    {}
    ~Stu()
    {
        cout << "Stu::析构函数" << endl;
    }
};
 
int main()
{
 
    Person *p = new Stu("张三",1001);
    delete p;   //如果没有虚析构函数,进行释放p是,子类自己拓展的空间就没有释放--内存泄漏
 
    return 0;
}

四、抽象类

纯虚函数是在 C++ 中用于实现接口和抽象类的一种机制。纯虚函数在基类中声明但不定义,它没有函数体,只有一个函数原型,并且必须在派生类中被重写(覆盖)。

在基类中声明纯虚函数会自动生成一个虚函数表(vtable),该表包含指向类中所有虚函数(包括纯虚函数)的指针。每个具有虚函数的对象都有一个隐藏的成员,即虚指针(vptr),它在对象构造时自动设置,用于指向与该对象类型关联的虚函数表。

派生类必须重写所有基类中的纯虚函数,否则该派生类也会成为一个抽象类,不能被实例化。这种多态行为不仅适用于使用 new 动态创建的对象,也适用于自动(栈)或静态存储期的对象,只要你通过基类指针或引用来访问它们。

如果一个类没有任何数据成员并且只有纯虚函数,通常将其称为接口。虽然构造函数不能是虚函数或纯虚函数,但析构函数可以(并且通常应该)是虚函数,以确保正确的析构行为。

virtual 函数返回值类型 函数名(形参列表) = 0; //纯虚函数

抽象类一般是用来被继承的,它不能实例化出具体的一个对象,抽象类中至少有一个纯虚函数。

#include <iostream>
#include <string>

// 基类(抽象类)
class Hero {
public:
  virtual void attack() = 0;  // 纯虚函数
  virtual void defend() = 0;  // 纯虚函数
};

// 派生类1
class Warrior : public Hero {
public:
  void attack() override {
    std::cout << "Wqm attacks!" << std::endl;
  }
//  void defend() override {
//    std::cout << "Wqm defends!" << std::endl;
//  }
};
class Warrior2 : public Warrior {
public:
//  void attack() override {
//    std::cout << "Wqm attacks!" << std::endl;
//  }
  void defend() override {
    std::cout << "Wqm defends!" << std::endl;
  }
};



// 派生类2
class Mage : public Hero {
public:
  void attack() override {
    std::cout << "Mage casts a spell!" << std::endl;
  }
  void defend() override {
    std::cout << "Mage uses a shield!" << std::endl;
  }
};

int main() {
  Hero* hero1 = new Warrior2();
  Hero* hero2 = new Mage();

  hero1->attack();
  hero1->defend();

  hero2->attack();
  hero2->defend();

  delete hero1;
  delete hero2;
  hero1=nullptr;
  hero2=nullptr;
  return 0;
}

五、模板

C++另一个编程思想——泛型编程,主要利用的技术 模板

两个重要的模板机制:函数模板和类模板

                                                ​​​​​​​        ​​​​​​​只是一个框架并不是万能的

5.1函数模板

建立一个通用的函数,其返回值类型或者形参类型 不具体制定,用一个虚拟的类型来代替。

template <typename T>
函数的声明或定义

template ----->表示开始创建模板
typename -->表明后面的符号是数据类型,typename 也可以用class代替
T  ----->表示数据类型,可以其他符号代替
#include <iostream>
 
 
using namespace std;
 
 
//创建函数模板
template <typename T>
void fun(T &a, T &b)
{
    T temp;
    temp = a;
    a = b;
    b = temp;
}
 
 
 
 
//void fun(int &a, int &b)
//{
//    int temp;
//    temp = a;
//    a = b;
//    b = temp;
 
 
//}
//void fun(double &a, double &b)
//{
//    double temp;
//    temp = a;
//    a = b;
//    b = temp;
//}
 
 
//void fun(char &a, char &b)
//{
//    char temp;
//    temp = a;
//    a = b;
//    b = temp;
//}
 
 
int main()
{
    int a = 10, b = 20;
    fun(a,b);
    cout << a << "  " << b << endl;
 
 
    double c = 1.3, d = 1.4;
    fun(c, d);
    cout << c <<  "  " <<  d << endl;
    return 0;
}

作业文章来源地址https://www.toymoban.com/news/detail-678651.html

#include <iostream>
#include <string>

// 基类(抽象类)
class Animal {
public:
  virtual void perform() = 0;  // 纯虚函数
  virtual void size()=0;
  virtual ~Animal(){}
};



class Lion : public Animal {
public:
  void perform() override{
    std::cout << "Jump" << std::endl;
  }
  void size() override{
    std::cout << "big" << std::endl;
  }
};

class Tiger : public Animal {
public:
  void perform() override{
    std::cout << "Sit Down" << std::endl;
  }
  void size() override{
    std::cout << "big" << std::endl;
  }
};


int main() {
  Animal* hero1 = new Lion();
  Animal* hero2 = new Tiger();

  hero1->perform();
  hero1->size();

  hero2->perform();
  hero2->size();

  delete hero1;
  delete hero2;
  hero1=nullptr;
  hero2=nullptr;
  return 0;
}

到了这里,关于C++ DAY6的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT day6

    目录 思维导图 学生管理系统 ui界面 头文件 源文件

    2024年01月15日
    浏览(36)
  • arm:day6

    实现UART通信: 1.键盘输入一个字符\\\'a\\\',串口工具显示\\\'b\\\'  2.键盘输入一个字符串\\\"nihao\\\",串口工具显示\\\"nihao\\\" uart.h uart4.c main.c

    2024年02月12日
    浏览(33)
  • 作业day6

    数据库 sqlite3 sq.db 如果sq.db存在则直接打开sq.db数据库,如果不存在则先创建再打开; ​ 系统命令 需要以 . 开头,不需要以 ; 结尾 .quit 退出数据库 .exit 退出数据库 .help 显示帮助信息,获取所有系统命令; ​ .table 查看当前数据库下的所有表格; .schema 查看表的结构 创建表格c

    2024年02月20日
    浏览(42)
  • 数据结构 day6

    1-xmind 2-递归实现程序:输入一个数,输出该数的每一位

    2024年02月10日
    浏览(39)
  • day6_C++

    stack.h stack.c } queue.c queue.c

    2024年02月09日
    浏览(27)
  • 刷题笔记 day6

     对于一个递增排序的数组,我们可以使用双指针; 定义指针 left 指向数组最左端元素 , 定义指针 right 指向数组最右端元素; 当 nums[left] + nums[right]    target 时,右移指针right; 当 nums[left] + nums[right]   target 时,左移指针left; 当 nums[left] + nums[right]  ==  target 时,输出结果。

    2024年02月13日
    浏览(29)
  • 【C刷题】day6

    1、以下叙述中正确的是( ) A: 只能在循环体内和switch语句体内使用break语句 B: 当break出现在循环体中的switch语句体内时,其作用是跳出该switch语句体,并中止循环体的执行 C: continue语句的作用是:在执行完本次循环体中剩余语句后,中止循环 D: 在while语句和do-while语句中无法

    2024年02月08日
    浏览(37)
  • QT DAY6作业

    1.学生管理系统,基于QT的数据库中数据表的增删改查 头文件 源文件 修改效果图 删除效果图 2.MP4视频的灰度显示和均衡模式 源文件 效果图 3.思维导图

    2024年01月16日
    浏览(36)
  • 蓝桥杯打卡Day6

    文章目录 N的阶乘 基本算术 整数查询 本题思路: 本题是关于高精度的模板题。  本题思路: 本题是高精度的模板题。 本题思路: 本题是高精度的模板题。

    2024年02月09日
    浏览(43)
  • DAY6之哈希基础

    首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。 哈希表是根据关键码的值而直接进行访问的数据结构。 这么这官方的解释可能有点懵,其实直白来讲其实数组就是一张哈希表。 哈

    2024年02月19日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包