C++学习笔记
作者:互联网
面向对象
面向对象是把数据及对数据的操作方法放在一起,作为一个相互依存的整体,即对象。对同类对象抽象出其共性,即类,类中的大多数数据,只能被本类的方法进行处理。类通过一些简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信。
//int a;
//类 对象
基本特征
面向对象方法首先对需求进行合理分层,然后构建相对独立的业务模块,最后通过整合各模块,达到高内聚、低耦合的效果,从而满足客户要求。
具体而言,它有3个基本特征:封装、继承和多态。
(1)封装是指将客观事物抽象成类,每个类对自身的数据和方法实行保护。类可以把自己的数据和方法只让可信的类或对象操作,对不可信的进行隐藏。
(2)继承可以使用现有类的所有功能,而不需要重新编写原来的类,它的目的是为了进行代码复用和支持多态。它一般有3种形式:实现继承、可视继承、接口继承。其中,实现继承是指使用基类的属性和方法而无需额外编码的能力;可视继承是指子窗体使用父窗体的外观和实现代码;接口继承仅使用属性和方法,实现滞后到子类实现。
(3)多态是指同一个实体同时具有多种形式,它主要体现在类的继承体系中,简单地说,就是允许将子类类型的指针赋值给父类类型的指针,然后父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。
继承与派生:
继承与派生是同一个过程从不同的角度看:
保持已有类的特性而构成新类的过程称为继承
在已有类的基础上新增自己的特性而产生新类的过程称为派生
一个子类继承父类时,可按照 public、private和protected 方式继承父类,每种继承方式的区别如下:
1) public继承方式
- 基类中所有public成员在派生类中为public属性;
- 基类中所有protected成员在派生类中为protected属性;
- 基类中所有private成员在派生类中不可访问。
2) protected继承方式
- 基类中的所有public成员在派生类中为protected属性;
- 基类中的所有protected成员在派生类中为protected属性;
- 基类中的所有private成员在派生类中仍然不可访问。
3) private继承方式
- 基类中的所有public成员在派生类中均为private属性;
- 基类中的所有protected成员在派生类中均为private属性;
- 基类中的所有private成员在派生类中均不可访问。
不管哪种继承方式,父类的私有成员都不可以访问,只有间接的(通过函数)通过公有成员才能获取到私有成员的值。
派生类对象仅当 public 派生时,对基类中的 public 成员有可访问/可修改的权限,其他都为不可访问/不可修改。
#include <iostream>
#include <String>
using namespace std;
// 基类
class student
{
public:
string name;
protected:
int age;
private:
char sex;
public:
void showStu()
{
cout << this->name << endl; // 1、在本类能够访问类的公有数据成员
cout << this->age << endl; // 1、在本类能够访问类的保护数据成员
cout << this->sex << endl; // 1、在本类能够访问类的私有数据成员
}
};
// 派生类 - public继承
class public_Sub : public student
{
public:
void show()
{
cout << this->name << endl; // 2、public继承,在派生类中能够访问基类的公有数据成员
cout << this->age << endl; // 2、public继承,在派生类中能够访问基类的保护数据成员
//cout << this->sex << endl; // error:2、在c类中不能访问基类的私有数据成员
}
};
// 派生类 - protected继承
class protected_Sub : protected student
{
public:
void show()
{
cout << this->name << endl; // 3、protected继承,在派生类中能够访问基类的公有数据成员
cout << this->age << endl; // 3、protected继承,在派生类中能够访问基类的保护数据成员
//cout << this->sex << endl; // error:3、在派生类中不能访问基类的私有数据成员
}
};
// 派生类 - private继承
class private_Sub : private student
{
public:
void show()
{
cout << this->name << endl; // 4、private继承,在派生类中能够访问基类的公有数据成员
cout << this->age << endl; // 4、private继承,在派生类中能够访问基类的保护数据成员 【即使是private继承】
//cout << this->sex << endl; // error:4、在派生类中不能访问基类的私有数据成员
}
};
int main()
{
student stu;
cout << stu.name << endl; // 5、在类外可以访问类的公有数据成员
//cout << stu.age << endl; // error,5、在类外不能访问类的保护数据成员
//cout << stu.sex << endl; // error,5、在类外不能访问类的私有数据成员
return 0;
}
虚函数:
指向基类的指针在操作它的多态类对象时,可以根据指向的不同类对象调用其相应的函数,这个函数就是虚函数。
虚函数的作用:在基类定义了虚函数后,可以在派生类中对虚函数进行重新定义,并且可以通过基类指针或引用,在程序的运行阶段动态地选择调用基类和不同派生类中的同名函数。(如果在派生类中没有对虚函数重新定义,则它继承其基类的虚函数。)
什么是多态性?
多态意指 “一个接口,多种实现”。一句话概括就是:
在基类的函数前加上virtual关键字,在派生类中重写该函数,运行时将会根据对象的实际类型来调用相应的函数。如果对象类型是派生类,就调用派生类的函数;如果对象类型是基类,就调用基类的函数,运行时绑定(动态绑定)。
(基类虚函数->子类覆盖->基类指针指向子类对象)
原理?
编译器为每个含有虚函数的类维护有一个虚函数表,而每个对象拥有一个虚指针(首地址保存),指向虚函数表,对象间共有虚表(vtable)。
虚表可继承,子类继承基类虚表后,虚表与父类虚表完全相同(地址不同),只是对象的虚指针指向了本类的虚表。
虚函数指针指向各自的虚表,虚表地址指向各个函数,当父类被继承时,重写函数时子类的虚指针指向的虚表地址与父类相同,运行时会根据对象更新地址,调用派生类函数。
其它没有被继承的仍然与父类虚指针指向地址相同 。如果不加virtual关键字,则仍然调用父类函数。
#include <iostream>
using namespace std;
//int a;
//类 对象
class tran {
public:
virtual void fun() {
cout << 3 << endl;
}
virtual void fun2() {
cout << 33 << endl;
}
virtual void fun3() {
cout << 333 << endl;
}
int x;
};
class plane : public tran {
public:
void fun() {
cout << 7 << endl;
}
int y;
};
void add(int a, int b) {
cout << a + b << endl;
}
int main() {
void(*pp)(int, int);
pp= add;
pp(1, 2);
typedef void(*tp)(void);
tran a; //3
plane b; //7
tran* p;
cout << sizeof(a) << endl << sizeof(b) << endl;
p = &a;
p->fun();
p = &b;
p->fun();
tp** p1 = (tp**)&a;
cout << p1[0][0] << '\t' << p1[0][1] << '\t' << p1[0][2] << endl;
p1 = (tp**)&b;
cout << p1[0][0] << '\t' << p1[0][1] << '\t' << p1[0][2] << endl;
}
//类 对象
C++中的 struct与class的区别是什么?
具体而言,在 C++ 中,class 和 struct 做类型定义时只有两点区别:
(1)默认继承权限不同。class 继承默认是 private 继承,而 struct 继承默认是 public 继承;
(2)class 还用于定义模板参数,就像 typename,但关键字 struct 不用于定义模板参数。
标签:虚表,函数,继承,基类,笔记,学习,C++,派生类,public 来源: https://www.cnblogs.com/wxk1213/p/15635979.html