C++学习笔记7_多态
1. 类与类之间的关系
class A
{
public:
int a;
void funcA()
{}
}
包含:
class B
{
public:
void funcB(){}
A a;
}
//如果类B有类A的成员变量,那么B has A,类B依赖于类A
使用:
class C
{
public:
void funC(A *a)
{
}
}
//C的成员方法需要A的形参,C use A
*B与A的耦合度比C要高。
//
继承:
class D:public A
{
void funcD()
{
}
D(int a):A(a) //与C#不同的地方,C#是D(int a):base(a),可能是C++有多重继承的原因
{
//..
}
}
*D si A,耦合度最高。
//为什么要写public 呢?应该是确定能否通过D来访问A的成员???
has A,use A, is A;
2.
A->B->C
A->B1->C1
B->D
B1->D
D是多继承
3.类的继承方式
这是和C#不同的地方,C#没有继承方式,继承就是继承了,就算有,C#都是public继承, A中的成员的“外部和继承可访问性”,继承后还是一样。
C++通过继承方式,限制了继承后,改变了原来A“对外和继承的可访问性”。
更多是private和protect的继承方式,对原来A中public的影响最大
*一般用public就行了,其他继承方式不建议使用。
4. 类的兼容原则
class A;
class Aplus:public A;
int main()
{
Aplus ap;
A a=ap;
}
//跟C#类似,能里氏替换,c#子类引用变量能赋值给父类引用变量;
//C++因为子类有父类的所有东西,所以能给父类的所有字段初始化;
//父类指针可以指向子类对象
//父类引用可以引用子类对象
//左父=右子(右子赋值(=号操作符)给左父,右子初始化左父(构造函数))
//子类能够满足父类指针、引用、变量的全部需求。反之不行。
5. 子类构造析构
构造函数,跟C#一样,会先调用父类的构造函数
6. 继承中,子类的成员和父类成员有重名:
子类内部
void func()
{
this->a=1;
A::a=1;//注意,这里要和使用静态的成员区分。
}
//一般都避免这样
//C++的继承其实是很粗暴的,内存的开辟直接堆上去,不管重不重名,有就堆上去。
//C#中,子类的字段不能和父类同名,属性也是,如果非要同名,要加public new int Age{ get;set;}
7.
class A
{
public:
static int a;//静态变量在静态区,继承方式是影响不了其访问性
}
int A::a=100;//静态变量初始化
//
int main()
{
A a;
cout<<a.a<<endl;
}
8. 多继承
//
class Furniture
{
public : int price;
}
class Sofa:public Furniture;
class Bed:public Furniture;
class SofaBed:public Bed,public Sofa;
//
那SofaBed就有两个price空间的大小了(c++粗暴的堆上去),那只能
int main()
{
SofaBed sb;
sb.Bed::price=100;
sb.Sofa::price=200;
}
//这是和C#不同的地方,C#没有多继承
9. 虚继承 (一般很少这样做)
**要不想这样子,给两个price赋值,那么只能:
class Sofa:vitual public Furniture;//加virtual
class Bed:vitual public Furniture;//加virtual
class SofaBed:public Bed,public Sofa;//不变
####出现棱形继承#####
**父类继承爷爷类的时候加virtual
**virtual继承,只是为了开辟“爷类”的字段一次
#区别开C#中的virtual方法,C#中virtual只是用来标记方法,能被子类重新,在以父类或者子类引用的方式调用时,均会执行子类的重写的方法。
10. C++中的虚方法(重要)
class A {
public:
function()
{
//...
}
};
class Aplus:public A
{
public:
function()
{
//...
}
}
//
int main()
{
A *a=new Aplus();//左父右子
a->Function();//这里是调用了A的fuction,不写成虚方法,就执行指针类型的funtion;
}
(这种又叫重定义,调用以A的指针调用function,那么执行A的function;以Aplus的指针调用function,那么执行Aplus的function。)
//这里又和C#不同了,同名方法没有标记为virtual都可以继承。
//C++是父类型指针变量,指向子类对象,能调用子类方法。
***如果想象C#一样,用父类变量引用子类对象,依然可以执行子类的方法。
解决办法:
class A {
public:
vitual function()//虚方法
{
//...
}
};
//这里又和C#不同了,子类不需要在方法前写override
****************但是,习惯上也在子类的方法前加virtual,做一个标识作用,就当做C#中的override****************
//在.cpp文件中,实现虚方法,就不需要加virtual了。
11. 虚析构函数(重要)
防止在使用“左父-右子”的父指针 delete father,如果不标记析构函数为virtual(原因见下),只能析构父类的空间。子类写成virtual析构,能两个析构都调用,不用自己再在子析构中,显式调用父析构。
***特别是用工厂方法new对象时,较为要紧*********
*在正常析构子类对象时,父类对象能自动析构
***********继承也要注意父析构函数标记virtual**********
13. vtpr指针(重要)。
vtpr指针,是指向虚函数表的指针。
例如:A中有virtual fun1(); Aplus重写;
fun1会放到A的虚函数表;fun1会放到Aplus的虚函数表;
当
A a=new Aplus();
a->fun1();
编译器发现fun1()是虚的,应该会额外标记(重要步骤)。在运行的时候,vtpr指针会去虚函数表找fun1的函数,因为a实质上是Aplus,所以实质上是去找Aplus的虚函数表。
//所以,如果A的fun1没标记为virtual,那么编译自然不会额外标记了,在运行时就只按照A类查找普通的函数表;
//小知识,同样的类,有函数加了virtual,那么sizeof(A)会莫名增大,因为多了vtpr指针的大小。
//不要在父类构造函数中调用virtual函数,否则子类vtpr指针还没初始化好,调的依然是父类的函数,vtpr指针是随着各个父类的构造函数,不断变换指向,直到最后的子类的。
14. 指针步长
A array[] = {Aplus(0),{Aplus(1),{Aplus(2)};//相当于C#A[] array = {new Aplus(0),..};
可以使用array代表是指向第一个元素的地址;
array++可以指向第二个元素;但是,要注意的是,array++是按A的内存大小,往下跳的,如果Aplus所占用的大小大于A,那么array++会跳到一个错误的位置。
15. 纯虚函数,抽象类(C++没有C#中的接口,但是有纯虚函数)
class shape{
public:
double height;
double weight;
virtual int func()=0;//=0只是一个语法,标记为纯虚函数。并不是返回值
shape(){}
virtual ~shape(){}//抽象类最好提供一下虚析构
}
//如果一个类有纯虚函数,那么就是抽象类,不管有没有普通函数。
//跟C#一样,抽象类不能实例化。
//跟C#一样,抽象类能继承抽象类。
/ /跟C#不一样,C#的抽象类必须写成abstract,而且可以写virtual函数,virtual函数能有实现,反而抽象函数,要标记开abstract
class A:public Interface;
C++学习笔记7_多态的更多相关文章
- SQL反模式学习笔记7 多态关联
目标:引用多个父表 反模式:使用多用途外键.这种设计也叫做多态关联,或者杂乱关联. 多态关联和EAV有着相似的特征:元数据对象的名字是存储在字符串中的. 在多态关联中,父表的名字是存储在Issue_T ...
- No2_3.接口继承多态_Java学习笔记_多态
***多态***1.多态性:通常使用方法的重载(Overloading)和重写(Overriding)实现类的多态:2.重写之所以具有多态性,是因为父类的方法在子类中被重写,方法名相同,实现功能不同. ...
- thinkinginjava学习笔记07_多态
在上一节的学习中,强调继承一般在需要向上转型时才有必要上场,否则都应该谨慎使用: 向上转型和绑定 向上转型是指子类向基类转型,由于子类拥有基类中的所有接口,所以向上转型的过程是安全无损的,所有对基类进 ...
- 1.12(java学习笔记)多态及向上、向下转型
一.多态 多态是指同一个方法被调用,由于对象不同导致行为不同. 例如调用自由活动方法,张三喜欢玩耍,那么他就会去玩耍. 李四喜欢学习,那么他可能去学习.调用方法因对象的不同 而产生了不同的行为. 形成 ...
- Thinking in java学习笔记之多态
多态是一种将改变的事物和未变的事物分离开来的重要技术.
- Java学习笔记之多态
1.父类型的引用可以指向子类型的对象: Parent p = new Child(); 2.当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误:如果有,再去调用子类的该同名方法 ...
- C++学习笔记:多态篇之虚析构函数
动态多态中存在的问题:可能会产生内存泄漏! 以下通过一个例子向大家说明问什么会产生内存泄漏: class Shape//形状类 { public: Shape(); virtual double ca ...
- C++学习笔记:多态篇之虚函数
一.类型 在引入多态之前,我们先来看一下多态的两种类型: 二.多态性的概念 多态一词最初来源于希腊语,意思是具有多种形式或形态的情形,在C++中是指同样的消息被不同类型的对象接收时导致不同的行为,这里 ...
- Java学习笔记之——多态、抽象
1. 多态 多态:同一种事物调用同一个方法有不同的表现行为.(同一类型操作,作用于某一类对象,可以有不同的解释,产生不同的执行结果) 应用场景;当你定义一个功能性的方法可以使用多态的概念 前提:子类继 ...
随机推荐
- MySQL中日期和时间戳互相转换的函数和方法
时间戳转换成日期 复制代码代码如下: FROM_UNIXTIME 例如: 数据表中 invest_time 存储的是时间戳,如 1429063399 使用 FROM_UNIXTIME 可以把时间戳转 ...
- Springboot + Mysql8实现读写分离
在实际的生产环境中,为了确保数据库的稳定性,我们一般会给数据库配置双机热备机制,这样在master数据库崩溃后,slave数据库可以立即切换成主数据库,通过主从复制的方式将数据从主库同步至从库,在业务 ...
- 【Java】访问mysql数据库视图
数据库连接Connect: package cn.hkwl.zaxq.mysql; import java.sql.Connection; import java.sql.DriverManager; ...
- VGG(2014),3x3卷积的胜利
目录 写在前面 网络结构 multi-scale training and testing 其他有意思的点 参考 博客:blog.shinelee.me | 博客园 | CSDN 写在前面 VGG(2 ...
- Python 3.8.0 正式版发布,新特性初体验
北京时间 10 月 15 日,Python 官方发布了 3.8.0 正式版,该版本较 3.7 版本再次带来了多个非常实用的新特性. 赋值表达式 PEP 572: Assignment Expressi ...
- 【DP合集】合并 union
给出一个 1 ∼ N 的序列 A ( A 1 , A 2 , ..., A N ) .你每次可以将两个相邻的元素合并,合并后的元素权值即为 这两个元素的权值之和.求将 A 变为一个非降序列,最少需要多 ...
- Flannel的VXLAN模式工作原理
跨主机通信的一个解决方案是Flannel,由CoreOS推出,最早支持的是UDP模式,但是因为性能太差被淘汰了, 过时的UDP模式 相比两台宿主机直接通信,多出了flanneld的处理过程,发出IP包 ...
- VirtualBox for Mac 6.0.14 开源免费虚拟机方案
VirtualBox for mac是一款开源虚拟机软件,你可以利用该软件在Mac OS平台上运行Windows软件,即可以在一定程度上弥补Mac OS平台软件不足的劣势,玩家也可以获得Windows ...
- 告别硬编码,mysql 如何实现按某字段的不同取值进行统计
上周我突然意识到,我在grafana上写的 sql 语句存在多处硬编码.这篇笔记将记录如何实现没有硬编码的sql语句,以及自学编程过程中如何应对自己的笨拙代码和难题不断的状况. 1.有效但粗笨的硬编码 ...
- 我要学并发-Java内存模型到底是什么
内存模型 在计算机CPU,内存,IO三者之间速度差异,为了提高系统性能,对这三者速度进行平衡. CPU 增加了缓存,以均衡与内存的速度差异: 操作系统增加了进程.线程,以分时复用 CPU,进而均衡 C ...