寒假90min速成C++面向对象编程笔记
2022-2-3
前言
本篇笔记内容来源于以下视频:时长约为90min C++面向对象编程B站速成课程
Part 1:类的基本概念
- 类
- 对象
- 成员数据
- 成员函数
class student:
{
public:
int age;
string name;
bool set(int a);
bool set(string a);
};
面向对象代码至少有三部分:
Part 2:常见函数
- 普通成员函数
- 构造函数,自动初始化对象
- 带参数的构造函数,动态初始化对象
- 析构函数,销毁对象
- 常成员函数,只读不写
- 静态成员函数,依赖于类,但不依赖于某个对象
Part 3:
3.1 公有和私有
- 公有部分可以随便使用,私有函数和属性需要在类的内部通过公有外壳来调用
//正规程序类定义的写法:
class student:
{
public:
bool set(int a);
bool set(string a);
bool read() const;
student();
student(int a,string b);
private:
int age;
string name;
};
- 一般把“方法”都放在public中
- 属性都放在private中
- 目的:是防止类的外部随便篡改数据
- 通过函数来修改数据时,一般都具有防错机制,满足了条件才可以改。(封装性)
3.2 类的派生与继承
子类可以获得父类的成员和方法,并且还能增加自己的成员和方法。
//把student类细分为本科生和研究生
class undergraduate : public student
{
public:
string course;//该属性是student类中没有的属性,如本科生的四级英语成绩
}
class psotgraduate : public student
{
public:
string research;//该属性是student类中没有的属性,如研究生的科研成绩
}
3.3 类在不同情况下的继承
public,private,protect
- 将父类student类定义的private替换为protect
- 对student本身无任何变化
- 同时student的protect部分可以集成到student的子类中
3.4 相同函数名执行不同内容
- 方法专属于某个类。不太确切的例子:同样是“+”,但是C中是ASCI码的相加,但python中就是字符串的拼接。
- C++中实现相同的函数名执行不同的内容,有三种方法:
- 重载
- 隐藏
- 在父类student和子类postgraduate中都定义了一个函数study(),会隐藏父类中的study().
- 巧记:逆子,不听父亲的话
- 覆盖(override)
3.5 多态
- 在父类子类所有函数声明都加virtual,并且定义父类指针
- 随着指针指向不同的对象,程序会自动找到不同类里的同名方法
3.5.1 回顾:结构体指针
不考虑继承时,类指针与结构体指针类似
student *p;//新建一个student类指针
student aa;//新建aa对象
p=&aa;//p指针指向aa对象
p->name;//相当于aa.name
p->study();//相当于aa.study(),对aa执行成员函数
student *p=new student(20,'张三');
delete p;//调用析构函数
3.5.2 考虑继承后,会变的复杂一些:
- 父类指针可以指向子类对象,但是子类指针不可以指向父类对象
- 虽然父指针指向了子类对象,但不能调用子类对象中的专有属性和方法,仍只能调用父类中的方法。
3.5.3 真正的多态和虚函数
- 分别在student,undergraduate,postgraduate建一个方法,都叫study
每个study学习内容都是不一样的 - 在所有子类父类study声明前加上关键字virtual,表示这是一个虚函数
- 为了突出重点省略了构造函数和其他属性
class student //学生类定义
{
public:
virtual void study();//声明study方法,前面加上virtual,是一个虚函数
}
void student :: study();//注意这里没有virtual
{cout<<"好好学习";}
//下面是研究生类定义
class postgraduate : public student
{
public://研究生的公有成员
virtual void study();//声明study方法,前面加上virtual,是个虚函数
}
void postgraduate :: study();/注意这里没有virtual
{
cout<<'芯片设计';//研究生学习芯片设计
}
//下面是本科生类定义
class undergraduate : public student
{
public://本科生的公有成员
virtual void study();//声明study方法,前面加上virtual,是个虚函数
}
void undergraduate :: study();
{
cout<<"英语四级";
})
//在三个类中都设置了同名虚函数,并且都没有参数(区分于重载,重载依赖于参数不同来区分),下面是主函数
//下为主函数
student aa;
postgraduate bb;
undergraduate cc;
student *p;//定义父类指针
p=&aa;//父类指针指向student对象
p->study();//父类指针调用student对象的方法,打印出“好好学习”
p=&bb;//父类指针指向子类postgraduate对象
p->study();//父类指针调用子类postgraduate的方法,打印出“芯片设计”
p=&cc;//父类指针指向子类undergraduate对象
p->study()//父类指针调用子类undergraduate的方法,打印出“英语四级”
- C++多态的核心,就是只要在程序开始时候设置一个父类指针,之后这个指针可以动态地指向不同的类,并且指针还可以动态地调用不同的类的方法,从而实现了不同数据类使用相同的方法。
- 重载是编译时决定,编译的过程中就确定了究竟用哪种study
- 多态是运行时决定,编译器将三种study形成虚函数表,编译器将三种不同的study放在内存中。
3.6 纯虚函数与抽象类
3.6.1 抽象类的定义
1 学生是一个类,拥有子类:研究生和本科生
2 如果一个学生对象张三,那张三一定是研究生或者本科生中的一员
3 单纯只属于学生类而又不属于任何一个子类的对象张三在现实生活中是不存在的
4 学生类不具有自己的对象,于是学生类被叫做抽象类
3.6.2 设置抽象类依赖纯虚函数,形式如下
class student
{
public:
student();//抽象类也可以构造函数
student(int a,string b);//构造函数重载
virtual void study()=0;//声明study方法,表明这是纯虚函数
}
//下面为主函数
student aa;//这里报错,不允许创建抽象类对象
student *p;//但是可以创建抽象类指针
postgraduate bb;//创建子类对象
p=&bb;//父类指针指向子类
p->study();//通过多态调用子类的study方法
/*使用了抽象类后,父类student依然可以用年龄姓名等基本成员,但是父类没有了自己的study方法————“好好学习”。
*/
当设置了virtual void study()=0;之后:
- student就是一个抽象类
- study()函数,纯虚函数没有定义,只有声明,其具体内容靠子类的多态来实现
- 依然可以创建一个student的指针,不能创建student对象了(见上代码报错部分)
写在后面
- 继承、封装、多态是面向对象的三大法宝,也是所有编程语言通用的
- C++的多态依赖于指针实现,而新兴语言如java、python、system、SV语言看似取消了指针,解放了程序员,其实是隐藏了指针。
- 如python中无需定义数据类型,直接a=10,a=‘aaa’,可以对a重新赋不同类型的值,实际就是在赋指针,使指针指向不同的区域。
- 在学习之后,我发现对于不同函数的理解仍然非常生疏他,同时缺乏项目实践操作,仍需在下一阶段继续学习。最近被Cherno小哥狠狠圈粉~
Cherno小哥的课程链接
|