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. 多态 多态:同一种事物调用同一个方法有不同的表现行为.(同一类型操作,作用于某一类对象,可以有不同的解释,产生不同的执行结果) 应用场景;当你定义一个功能性的方法可以使用多态的概念 前提:子类继 ...
随机推荐
- 常用注解@Controller、@Service、@Autowired
@Controller.@Service在spring-context-5.1.10.RELEASE.jar包下,所在包如下 @Autowired在spring-beans-5.1.10.RELEAS ...
- QR 码详解(下)
快速响应矩阵码(下) 书接上回,继续下半场. 纠错码 QR 码采用纠错算法生成一系列纠错码字,添加在数据码字序列之后,使得符号可以在遇到损坏时可以恢复.这就是为什么二维码即使有残缺也可以扫出来.没有残 ...
- TP框架配合jquery进行3种方式的多图片上传
用的TP5.1框架+jquery 一 使用form表单方式进行多图片上传 html代码: <form action="../admin/admin/cs" enctype=& ...
- Cocos2d-x入门之旅[1]场景
在游戏开发过程中,你可能需要一个主菜单,几个关卡和一个END的界面,如何组织管理这些东西呢? 和其他游戏引擎类似,Cocos也使用了场景(Scene) 这个概念 试想象一部电影或是番剧,你不难发现它是 ...
- 【JZOJ5329】-时间机器
[JZOJ5264]化学 Description Input Output Sample Input 3 10 1 2 10 Sample Output 5 Hint 题解: 这个题目又是一道贪心题, ...
- LeetCode 第 287 号问题:寻找重复数,一道非常简单的数组遍历题,加上四个条件后感觉无从下手
今天分享的题目来源于 LeetCode 第 287 号问题:寻找重复数. 题目描述 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个 ...
- conversion function——转换函数
类型转换函数 与 explicit关键字 1.类型转换函数 在C++中,可以使用构造函数将一个指定类型的数据转换为类的对象,也可以使用类型转换函数 (type conversion function) ...
- MySQL基础(三)多表查询(各种join连接详解)
Mysql 多表查询详解 一.前言 二.示例 三.注意事项 一.前言 上篇讲到Mysql中关键字执行的顺序,只涉及了一张表:实际应用大部分情况下,查询语句都会涉及到多张表格 : 1.1 多表连接有哪些 ...
- Java学习笔记之基础语法(顺序,条件,循环语句)
顺序结构:自上而下 条件分支选择结构: if条件语句 1,一旦某一个分支确定执行以后,其他分支就不会执行.if后面的条件必须是boolean类型 2,if 后面如果不加大括号,默认相邻的下一 ...
- 快速傅里叶变换(FFT)略解
前言 如果我们能用一种时间上比 \(O(n^2)\) 更优秀的方法来计算大整数(函数)的乘法,那就好了.快速傅里叶变换(FFT) 可以帮我们在 \(O(n\log n)\) 的时间内解决问题. 函数乘 ...