面向对象编程的特性: 抽象、封装、继承、多态
把属性和行为整合起来,外壳用类这个自定义的数据类型封装起来,该隐藏的隐藏起来,该暴露的暴露出来!一般属性都是隐藏起来的 private、protected; 行为都是暴露出来 public。
1)公有( public )成员可以在类外访问;
2)私有( private )成员只能被该类的成员函数访问;
3)保护( protected )成员只能被该类的成员函数或派生类的成员函数访问。
#include
using namespace std;
#include
/*
手机类:
属性:品牌、型号、运行内存、内存、价格、颜色、像素、尺寸、密码
行为:开机、关机、拍照、打电话、发短信、设置密码....
*/
class Phone
{
public:
void turnOn()
{
cout << "手机开机...." << endl;
}
void turnOff()
{
cout << "手机关机...." << endl;
}
void takePhoto()
{
cout << "手机拍照...." << endl;
}
void call()
{
cout << "手机呼叫...." << endl;
}
void sendMes()
{
cout << "手机发信息...." << endl;
}
void setPwd(string pwd)
{
this->pwd = pwd; //建议在类的成员函数中如果要访问类的成员,记得在成员前面加上this指针,
//可以避免当形参的名字和成员名字一样时,没法区分的问题!
}
void show()
{
cout << this << endl;
cout << "密码为:" <pwd << endl;
}
private:
string brand;
string type;
int ram;
int rom;
int price;
string color;
int pix;
int size;
string pwd;
};
定义一个数据类型,是不占内存空间的,但是它本身是有大小的;sizeof只有在定义变量的时候,才会分配内存空间!!!
类和对象在内存中的关系:所有的这个类的对象共用一份成员函数;这个类的所有的对象都拥有一份自己的数据成员。创建对象的时候,其实是给数据成员分配内存空间的!
int main()
{
//类对象的创建格式:数据类型名 对象名(变量名);
Phone myphoneA;
//访问:对象名.成员函数();
//myphoneA.turnOn();
return 0;
}
实现代码扩展
Is a -à继承关系 A is a B
这个已有的类称为基类,新建的类称为子类。例如,定义手机是基类,那么派生类可以是华为或者是苹果,等等。
#include
using namespace std;
#include
//人类: 属性:姓名、性别、年龄 行为:吃 、睡、show
//工人类: 属性:姓名、性别、年龄、工资 行为: work
class Person
{
public:
Person()
{
cout << "Person()" << endl;
}
~Person()
{
cout << "~Person()" << endl;
}
Person(string _name, string _sex="男", int _age=30):name(_name), sex(_sex),age(_age)
{
cout << "Person(string,string,int)" << endl;
}
void eat()
{
cout << this->name << "在吃饭...." << endl;
}
void sleep()
{
cout << this->name << "在睡觉...." << endl;
}
void show()
{
cout << "名字:" << this->name << "性别:" << this->sex << "年龄:" << this->age << endl;
}
protected:
string name; // 28
string sex;
int age;
};
class Worker :public Person
{
public:
Worker()
{
cout << "Worker()" << endl;
}
Worker(string _name, string _sex="男", int _age=30, int _salary=5000)
:Person(_name, _sex, _age), salary(_salary)
{
cout << "Worker(string,string, int, int)" << endl;
}
~Worker()
{
cout << "~Worker()" << endl;
}
void work()
{
cout << name << endl;
cout << "在工作....." << endl;
}
private:
int salary;
protected:
};
int main()
{
cout << sizeof(Person) << endl; // 60
cout << sizeof(Worker) << endl; // 64
Worker w("张三");
w.show();
return 0;
}
类继承父类的所有(数据成员、成员函数)
继承的格式是什么?
Class 子类名:继承方式 父类名{};
继承方式:
#include
using namespace std;
#include
//人类: 属性:姓名、性别、年龄 行为:吃 、睡、show
//工人类: 属性:姓名、性别、年龄、工资 行为: work
class Person
{
public:
Person()
{
cout << "Person()" << endl;
}
~Person()
{
cout << "~Person()" << endl;
}
Person(string _name, string _sex = "男", int _age = 30) :name(_name), sex(_sex), age(_age)
{
cout << "Person(string,string,int)" << endl;
}
void eat()
{
cout << this->name << "在吃饭...." << endl;
}
void sleep()
{
cout << this->name << "在睡觉...." << endl;
}
void show()
{
cout << "名字:" << this->name << "性别:" << this->sex << "年龄:" << this->age << endl;
}
protected:
string name; // 28
string sex;
int age;
};
class Worker :virtual public Person
{
public:
Worker()
{
cout << "Worker()" << endl;
}
Worker(string _name, string _sex = "男", int _age = 30, int _salary = 5000)
:Person(_name, _sex, _age), salary(_salary)
{
cout << "Worker(string,string, int, int)" << endl;
}
~Worker()
{
cout << "~Worker()" << endl;
}
void work()
{
cout << name << endl;
cout << "工人在工作....." << endl;
}
private:
protected:
int salary;
};
class Farmer :virtual public Person
{
public:
Farmer()
{
cout << "Worker()" << endl;
}
Farmer(string _name, string _sex = "男", int _age = 30, int _fieldCount = 10)
:Person(_name, _sex, _age), fieldCount(_fieldCount)
{
cout << "Farmer(string,string, int, int)" << endl;
}
~Farmer()
{
cout << "~Farmer()" << endl;
}
void work()
{
cout << name << endl;
cout << "农民在工作....." << endl;
}
private:
protected:
int fieldCount;//拥有几亩地
};
//多继承的格式:class 子类名:继承方式 父类1,继承方式 父类2,
class FarmerWorker :public Farmer, public Worker
{
public:
FarmerWorker()
{
cout << "FarmerWorker()" << endl;
}
FarmerWorker(string _name, string _sex = "男", int _age = 30, int _salary=5000, int _fieldCount = 10)
:Worker(_name, _sex,_age,_salary), Farmer(_name, _sex, _age, _fieldCount)
{
cout << "FarmerWorker(string,string, int, int)" << endl;
}
~FarmerWorker()
{
cout << "~FarmerWorker()" << endl;
}
void work()
{
cout << name << endl;
cout << "农民公在工作....." << endl;
}
private:
};
int main()
{
FarmerWorker fw("李四", "男",45, 6000, 5);
cout << sizeof(FarmerWorker);
return 0;
}
farmerWork类是继承Farmer类和Worker类;Farmer类和worKer类都是继承Person类farmerWork就会有两份从Person继承到的数据成员和成员函数!访问不明确。
解决方案:虚继承 virtual
1.静态编译多态(即重载)。=>相关知识点: c语言无法实现重载
2.运行多态(即重写,以虚函数方式),具体表现在通过基类的指针调用子类对象的方法。
动态多态,是基于封装和继承的来实现的,多个子类对继承于一个父类的虚函数进行重写,来实现不同状态。
1.必须有继承
2.父类中有虚函数,子类有重写这个虚函数(子类中的函数和父类中的这个函数的首部必须是一模一样的,只有函数体内部是不同的)
通过父类的指针或者是引用去调用这个虚函数的时候
#include
#include "sqlite3.h"
using namespace std;
#include
class Shape
{
public:
Shape()
{
cout << "Shape()" << endl;
}
virtual ~Shape()
{
cout << "~Shape()" << endl;
}
virtual float getArea()
{ return this->area; }
protected:
float area;
};
class Rect :public Shape
{
public:
inline Rect(int w=5, int h =3):w(w),h(h)
{
cout << "Rect(int ,int)" << endl;
}
~Rect()
{
cout << "~Rect()" << endl;
}
virtual float getArea()
{
cout << "矩形" << endl;
area = w*h;
return area;
}
private:
int w, h;
};
class Circle :public Shape
{
public:
Circle(int r=3):r(r)
{
cout << "Cricle(int)" << endl;
}
~Circle()
{
cout << "~Circle()" << endl;
}
float getArea()
{
cout << "圆形:" << endl;
area = r * r * 3.1415926;
return area;
}
private:
int r;
};
void calArea(Shape *p)//把子类对象的地址赋值给父类的指针,然后通过父类的指针去访问子类的成员函数,
// 只能访问到子类从父类中继承的成员函数
{
cout << p->getArea() << endl;
}
一个类中如果有虚函数,那这个类就有一张虚函数表,这个表中存的就是这个类所有虚函数的地址(函数指针数组)。
用父类的指针去释放子类的对象,析构只执行了父类的,没有走子类的析构(析构函数的作用),会存在内存泄漏问题。
父类的析构函数变成虚析构函数,就可以实现delete 父类指针也会执行子类析构的效果
重载:同一个作用域(构造函数重载)
重定义(隐藏): 在继承关系中,子类定义了和父类同名的函数(只有函数名相同—不包括虚函数)
重写:在继承关系中,子类重写了父类的虚函数(函数的首部是一模一样的)