C++之模板类指向子类对象(一百四十六)

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

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

C++之模板类指向子类对象(一百四十六),C++入门系列,c++,开发语言

1.前言

本篇目的:理解模板类指向子类对象应用。文章来源地址https://www.toymoban.com/news/detail-516998.html

2.应用实例

<1>.v1.0 基础版

#include<iostream>
using namespace std;

template<typename SERVICE>
class BaseA{
public:

  BaseA(){
    //printf("xxx--------->%s(), line = %d, i = %s\n",__FUNCTION__,__LINE__,SERVICE::getServiceName());
  }
  virtual void test(int i) = 0;//纯虚函数,子类必须实现.
};

class Parent{
public:
  Parent(){
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
};


//Derived继承自类模板BaseA<任意类型>.将子类的类型传参给模板类,在模板类可以调用子类Derived的getServiceName()和value
class Derived: public BaseA<Derived>{
  friend class BaseA<Derived>;
public:
  void test(int i){
    printf("xxx--------->%s(), line = %d, i = %d\n",__FUNCTION__,__LINE__,i);
  }
  static const char *getServiceName() { return "media.audio_policy"; }
  int value = 100;
};

int main(){
  //1.子类指向子类对象
  Derived *dr = new Derived();
  dr->test(777);
  printf("xxx--------->%s(), line = %d, value = %d\n",__FUNCTION__,__LINE__,dr->value);

  //2.父类指向子类对象
  BaseA<Derived> *b = new Derived;
  b->test(999);
  //printf("xxx--------->%s(), line = %d, value = %d\n",__FUNCTION__,__LINE__,b->value);//error
}

<2>.v2.0 升级版

#include<iostream>
using namespace std;

template<typename SERVICE>
class BaseA{
public:

  BaseA(){
    printf("xxx--------->%s(), line = %d, i = %s\n",__FUNCTION__,__LINE__,SERVICE::getName());
  }
  virtual void test(int i) = 0;//纯虚函数,子类必须实现.
};

class Parent{
public:
  Parent(){
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
  static const char *getName() { return "Hello Test."; }
};

class Derived: public BaseA<Parent>{
  friend class BaseA<Parent>;
public:
  void test(int i){
    printf("xxx--------->%s(), line = %d, i = %d\n",__FUNCTION__,__LINE__,i);
  }
  static const char *getServiceName() { return "media.audio_policy"; }
  int value = 100;
};

int main(){
  //1.父类BaseA<Parent>模板类指向子类对象Derived
  BaseA<Parent> *b = new Derived();
  b->test(999);
}

<3>.v3.0 仿Refbase例子

#include <iostream>
#include <string>

using namespace std;

class RefBase{
  public:
  RefBase(){
    printf("xxx---------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
};

class BpRefBase : public RefBase{
  public:
  BpRefBase(){
    printf("xxx---------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
};

template <typename INTERFACE>
class BpInterface : public INTERFACE, BpRefBase{
public:
  BpInterface(INTERFACE* ptr) : mPtr(ptr) {}
  void print(string cmd) {
    printf("xxx---------->%s(), line = %d, type(class) = %s\n",__FUNCTION__,__LINE__,typeid(INTERFACE).name());
  }
  INTERFACE *get(){
    return mPtr;
  }

  void takePicture() override {
    printf("xxx---------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }

  INTERFACE* mPtr;
};


class ICameraService {
public:
  virtual void takePicture() = 0;
};

class CameraService : public ICameraService {
public:

  void takePicture() override {
    printf("xxx---------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
};

int main() {
#if 0
  //第一种方式
/*
  CameraService 类是 ICameraService 接口的子类,而 BpInterface 类是一个模板类,它的模板参数是 ICameraService。在这个语句中,我们创建了一个 CameraService 类的对象,并将其赋值给了 BpInterface<ICameraService> 类型的变量 bpInterface。

  由于 CameraService 是 ICameraService 的子类,所以它满足了 BpInterface 类对模板参数的要求。因此,我们可以将 CameraService 对象赋值给 BpInterface<ICameraService> 类型的变量。

  这种用子类对象赋值给父类指针或引用的行为被称为多态。在多态中,我们可以使用父类的指针或引用来操作子类的对象,这样可以实现代码的灵活性和可扩展性。
  */
  //1.父类ICameraService指向子类对象CameraService
  BpInterface<ICameraService> bpInterface = new CameraService();

  //2.调用BpInterface类的成员函数print()
  bpInterface.print("123");

  //3.通过BpInterface类的mPtr指针,调用CameraService类重写的纯虚函数takePicture().
  bpInterface.get()->takePicture();
#else
  //第二种方式
  ICameraService *cameraService = new CameraService();
  BpInterface<ICameraService> *bpInterface = new BpInterface<ICameraService>(cameraService);
  bpInterface->print("123");
  bpInterface->get()->takePicture();
#endif

  return 0;
}


<4>.v4.0 父类指针指向子类对象区别

(1).
#include<iostream>
#include <typeinfo>
using namespace std;

template<typename SERVICE>
class BaseA{
public:
  BaseA(){
    mptr = new SERVICE;
  }
  void test(){
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }

    SERVICE *get(){
    return mptr;
  }
  SERVICE *mptr;
};

class Parent{
public:
  static const char *getName() { return "media.audio"; }
};

class Derived: public BaseA<Parent>{
  friend class BaseA<Parent>;
public:
  Derived(){}
};

int main(){
  //1.父类BaseA<Parent>模板类指向子类对象Derived
  BaseA<Parent> *b = new Derived();

  //2.调用类模板BaseA的成成员函数test.
  b->test();

  //3.调用传入模板类的Parent的成员函数getName.
  const char *name = b->get()->getName();
  printf("xxx--------->%s(), line = %d,name = %s\n",__FUNCTION__,__LINE__,name);

}

(2)
#include<iostream>
#include <typeinfo>
using namespace std;

#define NTD

template<typename SERVICE>
class BaseA{
public:
  BaseA(SERVICE *ptr) : mPtr(ptr){
    printf("xxx--------->line = %d, type = %s, name = %s\n",__LINE__,typeid(SERVICE).name(),SERVICE::getName());
  }
  SERVICE *get(){
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
    return mPtr;
  }
  void test(){
    printf("xxx--------->%s(), line = %d\n",__FUNCTION__,__LINE__);
  }
  SERVICE *mPtr;
};

class Parent{
public:
  static const char *getName() { return "media.audio"; }
  int value = 100;
};

class Derived: public Parent{
public:
  int count = 200;
};

int main(){
    //第一种方式:
  //1.父类BaseA<Parent>模板类指向子类对象Derived
  BaseA<Parent> b = new Derived();
/*
  将Parent类传入类模板BaseA,接着进入BaseA模板类构造函数初始化列表,进行初始化,将类Parent指针对象ptr传递给传给模板类的BaseA的成员变量mPtr,模板类b,因为Device继承自Parent类,将Device对象赋值给b。
  子类对象赋值给父类指针或引用的行为被称为多态。在多态中,我们可以使用父类的指针或引用来操作子类的对象
*/
  //2.调用类模板BaseA的成成员函数test.
  b.test();

  //3.调用传入模板类的Parent的成员函数getName.
  const char *name = b.mPtr->getName();
  printf("xxx--------->%s(), line = %d,name = %s\n",__FUNCTION__,__LINE__,name);

  //4.
  int val = b.get()->value;
  printf("xxx--------->%s(), line = %d,val = %d\n",__FUNCTION__,__LINE__,val);


  //第二种方式:
  BaseA<Parent> *bb = new BaseA<Parent>(new Derived());
  bb->test();
  const char *name_01 = bb->mPtr->getName();
}

<5>.v5.0 仿CameraService::instantiate()例子

#include <iostream>
using namespace std;

template<typename SERVICE>
class BinderService{
public:
  static void instantiate() {
    printf("xxx-------->line = %d, service_name = '%s'\n",__LINE__,SERVICE::getServiceName());

    SERVICE *cm = new SERVICE();
    printf("xxx-------->line = %d, count = %d, type(name) = %s\n",__LINE__,cm->count,typeid(SERVICE).name());
  }
};

class CameraService : public BinderService<CameraService>{
  friend class BinderService<CameraService>;

  static char const* getServiceName() { return "media.camera"; }
  int count = 220;
};

int main(){
  //way01:
  CameraService::instantiate();

  //way02:
  CameraService *cm = new CameraService;
  cm->instantiate();
}

到了这里,关于C++之模板类指向子类对象(一百四十六)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 海信电视LED55N3000U(000)版本刷机(一百四十七)

    需求: 电视内存不足,导致无法安装第三方app? 推荐四种解决方案: 注意:U盘格式化成FAT32格式。 ---------设置 ---------通用设置 ---------把”商场模式“打开 ---------插入U盘,打开\\\"应用安装到U盘\\\",如果打开不成功,开关机,多试几次。 二、打开\\\"开发者模式\\\" ---------设置 ------

    2024年02月05日
    浏览(56)
  • 一百四十三、Linux——Linux的CentOS 7系统语言由中文改成英文

    之前安装CentOS 7系统的时候把语言设置成中文,结果Linux文件夹命名出现中文乱码的问题,于是决定把Linux系统语言由中文改成英文 # cd /etc/ # ls # vi locale.conf 就是把原先的LANG=\\\" zh_CN .UTF-8\\\"修改为LANG=\\\" en_US .UTF-8\\\"  修改好后:wq保存并退出配置文件locale.conf # reboot  然后在上方页面

    2024年02月14日
    浏览(54)
  • 一百四十七、Kettle——Linux上安装的kettle8.2连接ClickHouse数据库

    kettle8.2在Linux安装好后,需要与ClickHouse数据库建立连接 https://pan.baidu.com/s/1iqGyXsTaQSCHEbjj7yX7AA 提取码: mvzd   注意 : clickhouse-plugins文件里就是自定义的驱动jar包 注意: 要知道Linux系统架构是64位还是32位, 它们所属的Linux文件夹不同 到这里,Linux安装的kettle8.2就可以与ClickHou

    2024年02月13日
    浏览(66)
  • 一百四十一、Kettle——kettle8.2在Windows本地开启carte服务以及配置子服务器

    在kettle建好共享资源库后,为了给在服务器上部署kettle的carte服务躺雷,先在Windows本地测试一下怎么玩carte服务 kettle版本是8.2             pdi-ce-8.2.0.0-342     kettle本地安装路径是D:javakettlepdi-ce-8.2.0.0-342 Carte是Kettle自带的调度及监控工具,是一种内置的轻量级的web服务,支

    2024年02月10日
    浏览(55)
  • 一起Talk Android吧(第五百四十六回:如何判断手机是否安装GooglePlay)

    各位看官们大家好,上一回中咱们说的例子是\\\"如何实现流水动画\\\",本章回中介绍的例子是\\\" 如何判断手机是否安装GooglePlay \\\"。闲话休提,言归正转,让我们一起Talk Android吧! 我们在这里说的 GooglePlay 就是Google的应用市场,它本质上也是应用程序,只是在国内无法使用,因此部

    2024年02月09日
    浏览(56)
  • 一百四十九、Kettle——Linux上安装的kettle8.2创建共享资源库时遇到的问题(持续更新中)

    在kettle8.2在Linux上安装好可以启动界面、并且可以连接MySQL、Hive、ClickHouse等数据库后开始创建共享资源库,但是遇到了一些问题 1、报错详情 2023/08/10 13:57:21 - Spoon - Caused by: java.lang.UnsatisfiedLinkError: Could not load SWT library. Reasons:  2023/08/10 13:57:21 - Spoon -     no swt-mozilla-gtk-4335 i

    2024年02月13日
    浏览(68)
  • 【C/C++】父类指针指向子类对象 | 隐藏

    创作不易,本篇文章如果帮助到了你,还请点赞 关注支持一下♡𖥦)!! 主页专栏有更多知识,如有疑问欢迎大家指正讨论,共同进步! 🔥c++系列专栏:C/C++零基础到精通 🔥 给大家跳段街舞感谢支持!ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ ዽ ጿ ኈ ቼ c语言内容💖:

    2024年02月11日
    浏览(42)
  • C++笔记之基类指针动态地指向某一个子类情况列举

    code review!

    2024年02月12日
    浏览(49)
  • 第一百一十六天学习记录:C++提高:STL-string(黑马教学视频)

    string是C++风格的字符串,而string本质上是一个类 string和char 区别 1、char 是一个指针 2、string是一个类,类内部封装了char*,管理这个字符串,是一个char 型的容器。 特点: string类内部封装了很多成员方法 例如:查找find,拷贝copy,删除delete替换replace,插入insert string管理char

    2024年02月15日
    浏览(47)
  • 一起Talk Android吧(第五百四十回:ImageView的缩放)

    各位看官们大家好,上一回中咱们说的例子是\\\"RxJava中的总结\\\",本章回中介绍的例子是\\\"I mageView的缩放 \\\"。闲话休提,言归正转,让我们一起Talk Android吧! 通常情况下ImageView组件主要用来显示图片,因此需要使用图片当作显示内容,这个可以通过 ImageView 的src属性来设置被显示的

    2023年04月09日
    浏览(48)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包