如何实现:A类中创建并使用了B类的对象,现在写一个C类继承B类,同时A类也被修改为创建C类

深林孤鹰 2020-01-17 08:31:31
假设写个模型:
class B
{

};

class A
{
public:
B* pB;
void init()
{
pB = new B;
}
};

现在想扩展B类的,但是不修改A类,使A类init函数创建C类的对象,如何能实现呢?
class C:public B
{
void extend(){...}
}

现在能想到的解决方案有2个:模板类(得公开源代码)和回调函数(将init修改为回调,太麻烦),不知有没有什么奇淫技巧来实现呢~谢谢
...全文
723 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
Linkkk丶 2020-01-18
  • 打赏
  • 举报
回复
外部实例化B或者C, 指针传入init,虚函数各自调用对象的成员函数
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
是的,B函数只是框架最基础的功能,然后客户可以扩展一些数据,甚至可以写逻辑。
感谢大家的回答~
真相重于对错 2020-01-17
  • 打赏
  • 举报
回复
既然C继承于B 完全可以 void init() { pB = new C; }
寻开心 2020-01-17
  • 打赏
  • 举报
回复
所以
A是如何实现的,以及对pB这个数据对象的约束,是能否扩展的关键

如果pB是可以在A的对象初始化或者其他阶段通过传参进入的,那么你的扩展非常容易
大不了把B的一些方法虚化(virtual),甚至B本身都可以是个纯虚类,实际使用的时候用B的派生类, A调用B的这些方法就没有顾忌了

那些标准的模板是怎么样的,包括你说的回调函数, 其实都把数据做活了, 让B类的方法和数据不由A控制死
弓人水 2020-01-17
  • 打赏
  • 举报
回复
模板类应该能满足吧,A和B类不需要要公开源代码,派生类按照各自需求实现即可。
class A
{
public:
B* pB;

template<class T>
void init()
{
pB = new T;
}
};
...
A a;
a.init<B>();
a.init<C>();
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
禁止类的继承比较简单 直接用类厂造就行,把各种构造函数都做成private。
真相重于对错 2020-01-17
  • 打赏
  • 举报
回复
既然A不让改,那么封装A 参考一下proxy模式
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
我最初的构想就是做个框架,框架实现了一些通用的功能,还可以在不修改源码的情况下再次扩展功能。c++语言想要跳出原来代码去执行扩展代码再返回,也想来想去也就是回调函数、派生类和模板类了,但模板类必须开源整个类,还不如直接修改源码;回调函数方便,效率高,但可读性差也容易出错。刚才想到的那个办法比较优雅,其实是用到了c++的动态性特性,创建对象时用一个类厂对象去创建,扩展功能后重新继承派生那个类厂,这样就动态的去创建了B的派生对象C。而C对象由于继承自类B,所以完全不影响A的内部运行。
举个例子,一个列表实现就可以用这个方法,list类管理多个node对象,用户可以将自己的数据保存在node类的派生类中。
寻开心 2020-01-17
  • 打赏
  • 举报
回复
即便A里面的pB是pulic的, 但是能随意把它delete掉,或者用新的函数替代init函数来完成b的创建吗
这个还是取决于A已有的实现方式
如果A在构造的时候,就内部调用了init完成了pB的初始化,并做了其他的一些关联性操作,你就没法替换他
你可以继承A,再弄一套数据管理出来, 但是那还是A吗? 某种意义上是复制了一套新的出来。
A是你自己的代码或者开源的,是可以改造;
如果来自他人的系统,没有源码级的改造,只能在继承类上想办法
能否实现,还是取决于A的具体实现方式, A是完全能堵死这些可能性的。
有些商业软件就是这样, 它的对象禁止再继承,禁止再修改内部数据类型。
寻开心 2020-01-17
  • 打赏
  • 举报
回复
不改A没有办法吧
A里面的Init函数,没有传参, pB = new B; 这个写死了。
无论如何都是B对象了,没有办法把它改成C对象
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
引用 5 楼 弓人水 的回复:
既然,A类不能修改,且内部管理B类,那么无法让A去管理扩展的C了,因为既然new的是B类,就不可能动态让B变成C类了。


其实如果不用类模板,就得想办法在创建B类对象时跳转到其他地方下功夫。回调函数是个好办法,不过受你的启发用模板类、类厂和重载函数来优雅的实现了这个办法(其实核心仍然是跳转,只是代码比回调函数好看些)。大体实现如下:
创建一个类厂F,成员函数ceate来创建B类对象;
把F类的指针f定义在A中,把A类所有创建B类对象,都改为为f.create();
写C类派生A类,然后用另一个类厂FF派生F类,重写create,内容是创建C类对象;
将FF的对象赋值给A对象的f指针。
虽然比较麻烦,但是用起来还是挺方便的~
甚至可以把F和FF写到A类内,FF做成模板类会更方便,哈哈~
  • 打赏
  • 举报
回复
既然
public:
B* pB;
从外部直接创建个C实例然后设置pB即可
弓人水 2020-01-17
  • 打赏
  • 举报
回复
既然,A类不能修改,且内部管理B类,那么无法让A去管理扩展的C了,因为既然new的是B类,就不可能动态让B变成C类了。
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
引用 2 楼 真相重于对错 的回复:
既然C继承于B
完全可以
void init()
{
pB = new C;
}

不行啊,前提是不能更改A类代码(init函数等)。
深林孤鹰 2020-01-17
  • 打赏
  • 举报
回复
引用 1 楼 弓人水 的回复:
模板类应该能满足吧,A和B类不需要要公开源代码,派生类按照各自需求实现即可。
class A
{
public:
B* pB;

template<class T>
void init()
{
pB = new T;
}
};
...
A a;
a.init<B>();
a.init<C>();

谢谢!不过我的例子可能不恰当,因为A类没有类似init函数去创建B类,A是内部自己管理B类的创建和释放的,所以没办法把模板参数传递进去...
用模板类的话只能把整个A类都作为模板,不过这样得把所有代码暴露出来。
该课程由付强老师主讲,系统的、全面的、具体的讲解了java入门的知识。可以使初级的学员入门。Java入门Java的历史、Java的版本、Java的优势、软件行业前景Java开发环境搭建、编Java入门练习虚拟机的运行机制、Java的平台无关性、虚拟机垃圾回收机制基础语法关键字、标识符、Java数据型分、基础数据型、取值范围变量、常量、三种注释、生成doc文档、运算符、表达式if语句、switch语句、嵌套判断for语句、while语句、do-while语句、嵌套循环对象面向过程和面向对象的区别的构成、访问修饰符、对象的内存分配this关键字、按值传递与按引用传递、对象的初始化顺序高级特性继承、父子的初始化顺序、单继承性方法的覆盖、重载、super关键字、多态、instanceof关键字、强制型转换、static关键字、final关键字数组和枚举一维数组的应用及内存分配多维数组的应用及内存分配数组的复制、数组的按引用传递排序算法:冒泡、直接选择、插入选择、希尔、快速、归并、堆排序Arrays工具的应用枚举型的应用常见使用Object的底层及应用、ObjectsString的底层及应用、正则表达式StringBuffer和StringBuilder的底层及应用Math的应用、包装的应用日期的应用:Date、DateFormat、Calendar、LocalDateTime、Instant、LocalDate、MonthDay、ZonedDateTime、YearMonth、新旧日期转换BigInteger和BingDecimal、DecimalFormatSystem、Scanner抽象和接口抽象的规则及应用接口的规则及应用默认方法、静态方法、函数式接口、Lambda表达式异常异常的定义异常的处理:抓(try-catch-finally)、抛(throws)异常的分、自定义异常的应用、throw关键字集合框架集合框架结构:接口、实现Collection接口的方法、Set接口的方法、List接口的方法、Map接口的方法Array、Linked、Hash、Tree底层实现原理泛型的作用、Collections工具、历史集合I/O流Path的原理及应用、Files的原理及应用文件字节流FileInputStream的原理及应用对象、缓冲流、数据流的原理及应用字符流的原理及应用多线程进程与线程的概念、查看线程对象Java内存模型线程的创建与启动:扩展Thread实现Runnable接口、实现Callable接口、线程池线程状态的转换:新建、就绪、运行、阻塞、死亡线程的调度:sleep、yield、join、interrupt、wait后台线程、定时任务线程的并发与同步、同步锁、同步块、线程安全的Lock接口、CAS、volatile修饰符内部成员内部、本地内部的应用匿名内部的原理及引用、Lambda表达式设计模式基础设计模式概念、框架概念7大设计原则:开闭原则、依赖倒置原则、单一职责原则、接口隔离原则、迪米特原则、里氏替换原则、合成复用原则单例模式、工厂模式、模板模式、代理模式、装饰模式、适配器模式、外观模式、策略模式、观察者模式、命令模式、备忘录模式、观察者模式反射反射包Class使用反射获取属性、方法、构造器通过反射创建对象/通过反射调用方法反射的应用

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧