类并不是c++中的结构体变量
c++语言的特性:
多态 继承 抽象 封装
string cstring string.h dou
类和结构体的区别
1.结构体是⼀种值类型,⽽类是引⽤类型。值类型⽤于存储数据的值,引⽤类型⽤于存储对实际数据的引⽤。那么结构体就是当成值来使⽤的,类则通过引⽤来对实际数据操作。
2. 结构体使⽤栈存储(Stack Allocation),⽽类使⽤堆存储(Heap Allocation)栈的空间相对较⼩.但是存储在栈中的数据访问效率相对较⾼.堆的空间相对较⼤.但是存储在堆中的数据的访问效率相对较低.
3.类是反映现实事物的⼀种抽象,⽽结构体的作⽤只是⼀种包含了具体不同类别数据的⼀种包装,结构体不具备类的继承多态特性
4.结构体赋值是 直接赋值的值. ⽽对象的指针 赋值的是对象的地址
5.Struct变量使⽤完之后就⾃动解除内存分配,Class实例有垃圾回收机制来保证内存的回收处理。
6.结构体的构造函数中,必须为结构体所有字段赋值,类的构造函数⽆此限制⾸先,关于隐式构造函数.我们知道,在1个类中如果我们没有为类写任意的构造函数,那么C++编译器在编译的时候会⾃动的为这个类⽣成1个⽆参数的构造函数.我们将这个构造函数称之为隐式构造函数 但是⼀旦我们为这个类写了任意的1个构造函数的时候,这个隐式的构造函数就不会⾃动⽣成了.在结构体中,就不是这样了,在结构体中隐式的构造函数⽆论如何都存在。所以程序员不能⼿动的为结构添加1个⽆参数的构造函数。
7.结构体中声明的字段⽆法赋予初值,类可以
如何选择结构体还是类
1. 堆栈的空间有限,对于⼤量的逻辑的对象,创建类要⽐创建结构好⼀些
2. 结构表⽰如点、矩形和颜⾊这样的轻量对象,例如,如果声明⼀个含有 1000 个点对象的数组,则将为引⽤每个对象分配附加的内存。在此情况下,结构的成本较低。
3. 在表现抽象和多级别的对象层次时,类是最好的选择
4. ⼤多数情况下该类型只是⼀些数据时,结构时最佳的选择
多态性
在面向对象的方法中,多态性是指向不同对象发送同一个消息,不同对象在接收时会产生不同的行为(方法)。
通俗点说就是可以不用像 C 语言中为了求多种图形的面积而针对不同的图形各设计一个独立名字的函数,在 C++ 中只要设计一个专门用于求面积的函数名即可。这个专门用于求面积的函数名可以作为各种求图形面积的函数名。
这么做的好处在于程序设计者可以省去设立多个函数名对应多个函数的麻烦,使用的时候统一用同一个函数名就可调用具有不同功能的函数。
多态在 C++ 中的实现可以是函数的重载、运算符的重载和虚函数,本实训我们介绍虚函数的使用。
学习通:
第一章:
面向对象的程序设计中,把对象的属性(属性由数据表示,描述对象的静态特征)和行为(行为用代码表述,描述对象的动态特征)组织在同一个模块的机制叫做封装
类通过接口与外界发生关系
对象与对象之间的通信机制是消息
在结构化程序设计方法(面向过程)程序=算法+数据结构
在面对对象程序设计方法 程序=对象+信息
- 重载不是面向对象系统所包含的要素,面向对象=对象+类+继承+消息+多态
- 对象并不是功能相对独立的一段程序,对象之间可以通过消息相互通信
第二章:
- 函数可无原型 这样的话默认参数就可以设置在函数的定义语句中
- 内联函数可以加快程序运行速度,但是会增加代码的大小
- cout是预定义的标准输出流对象,<<是输出操作符/插入运算符
- 程序中必须包含头文件 iostream(记住直接写这个就行了)
- 注意看清楚问的是注释符号还是注释方式
- c++内存主要分为四个区:堆区(动态),栈区(局部变量),代码区,数据区(全局变量,静态变量)四个区的存储以及数据类型的区分
- const说明常量,需要指出类型,但如果定义的是整型常量,那么int可以省略
第三章:
- 创建对象时,类可以作为样板,对象被称作类的实例
- 在函数外部可以使用静态局部变量吗?不能
- 类中的数据成员不能在声明的时候初始化
- 静态数据和静态成员函数可以由任意访问权限允许的函数访问
- 类的成员函数和友元函数都可以访问类的私有数据成员
- 定义了指针,未初始化,因此不会分配内存但是占用空间,但是如果*p=new int,即是没有初始化,也会分配内存(按理说指针没有初始化是不会分配内存的,但是我刚刚试了一下,通过sizeof或者直接输出指针所指向的值发现都可以输出,但是记住一件事!!指针在初始化之前是不会调用构造函数的)
- 通常拷贝构造函数的参数是某个对象的引用名
- 将类的一个对象赋值给该类的另外一个对象时,不会调用拷贝构造函数。但是如果将类的一个对象初始化,另外一个对象就会调用。
- 关于new的用法:
- new创建对象时,创建对象的时候调用了(默认)构造函数
class A;
A *p=new A(<参数列表>)//参数列表中参数的个数与构造函数有关,如果不写参数那么就赋予默认值
delete p;
A *p=new A[6]//设置A的数组,有六个,这个地方数组的大小可以是变量
delete[]p;//该运算符也适用于空指针,但是必须是有new创建的
第四章:
- 若不是公有继承,派生类可以直接给基类赋值吗?不可以 !
- 单继承中,派生类对象对基类成员函数的访问不会出现二义性
- 继承是将通用的类变成特殊的类,将已有的类添加新的特性但不重写他们的方法
- 作用域运算符通常用来指定特定的类,解决二义性
- 如果基类没有默认构造函数,那么派生累就应当声明带形参的构造函数
-
第四章
一.重要定义之间的逻辑关系:
Has-A包含关系(子对象),Uses-A(一个类部分使用另一个类),Is-A继承
其中Is-A就是继承(派生)
继承有关的概念:
派生类中的访问控制:
私有继承,默认情况是私有继承
公有继承 : 其中公有继承有关的概念:赋值兼容原则,即在公有继承下,派生类可以当作基类使用,有三种情况(赋值给基类的对象,基类的引用,基类的指针)
保护继承:保护继承时,基类的成员有双重身份,在派生类内部是公有,在派生类外部是私有
继承的两种方法:
单继承,多继承
多继承-----二义性 (二义性只会在多继承的情况下发生)支配规则
二义性发生的两种情况:基类有相同的成员名,派生类两次间接从同一基类继承
支配规则:类X中的名字N支配类Y中同名N,指类X以Y为他的一个基类
#include<iostream> using namespace std; class Base1 { public: void show(){cout<<"hello"<<endl;}; private: int a; }; class Base2 { public: void show(){cout<<"world"<<endl;}; private : int b; }; class Derived :public Base1,public Base2 { public: void show(); }; void Derived::show()//注意是先void然后再derived { Base1::show(); Base2::show(); }
继承时特殊的函数,构造函数(包括拷贝构造函数),析构函数,不可以被继承,因此需要在调用派生类构造函数的时候显式调用基类的构造函数
构造函数的调用顺序:
先虚基类,然后基类,然后子对象,然后自身析构函数顺序相反
第六章 运算符重载
运算符必须背重载为非静态成员函数或者友元函数
一般情况下,重载运算符既可以为友元函数,也可以为成员函数,有时友元函数比成员函数更加灵活,例如12+Complex,但需要注意
1.赋值运算符不能被重载为友元函数
2.()[]不能被重载为友元函数
3.在重载增量运算或者减量运算符的时候,若使用友元函数,则需要引用参数
friend Complex operator ++(Complex & a,int)
{
Complex temp;temp.real=a.real++;
return temp;
}
第七章 虚函数
- 使用虚函数保证了在通过一个基类类型指针(含引用)调用一个虚函数时,C++对其调用进行的是动态联编,通过一个对象访问一个虚函数使用的是静态联编
- 要实现动态联编必须使用基类指针调用虚函数
- 通过抽象类调用基函数需要再设置一个外部接口
void func(Base& b){
b.function();}
- 为了区分重载函数,把一个派生类中重定义基类的虚函数称为覆盖
- 一个类中的虚函数说明只对派生类中重定义的函数有影响,对它的基类中的函数没有影响
- 因为没有纯虚函数定义代码,所以在构造函数和析构函数内均不可调用纯虚函数