类的定义
#include <iostream> #include <string> using namespace std; //class 的限令符:public 公共的,protected 受保护的,private 私有的 class Coordinate { public: void addrun(int x, int y) { int_x = x; int_y = y; } int get_run() { return int_x + int_y; } int int_x; int int_y; }; //class类有两种实例化对象的方法:分别有 int main01() { //1.从栈中实例化对象,栈中实例化对象会自动释放掉 Coordinate Coor;//定义在栈中的对象 Coor.addrun(20, 30); Coor.int_x = 50; cout << Coor.get_run() << endl; //2.从堆中实例化对象,也就是定义指针去实例化 Coordinate * p = new Coordinate(); if (p == NULL) { return 0;//判断是否申请内存成功 } p->int_x = 80; //访问类中的成员 p->int_y = 120; cout << p->get_run() << endl; //访问类中定义的函数 delete p; // 释放掉 p 申请的内存 p = NULL; // 把指针 p 设置成空指针 //到这里堆的实例化才算完 system("pause"); return 0; }
分文件处理
#include "Teacher.h"
以下就是类外定义了,也就是将函数的方法定义到了外边,在类中申明有这么个函数
分文件类外定义也是差不多的,也就是将类放到了 .h 的头文件中
将类外的那些方法定义到另外一个cpp文件中,但是必须要引用这个 .h 文件
到时候主文件调用也是调用.h文件
#include <iostream> #include <string> #include "stdlib.h" using namespace std; class Teacher { public: void setName(string name); string getName(); void setGender(string gender); string getGender(); void setAge(int age); int getAge(); void teach(); private: string var_name; string var_gender; int var_age; }; // #include "Teacher.h" void Teacher::setName(string name) { var_name = name; } string Teacher::getName() { return var_name; } void Teacher::setGender(string gender) { var_gender = gender; } string Teacher::getGender() { return var_gender; } void Teacher::setAge(int age) { var_age = age; } int Teacher::getAge() { return var_age; } void Teacher::teach() { cout << "快了" << endl; }
构造函数初始化列表
构造函数初始化列表//
默认构造函数
初始化列表的特性:
初始化列表先于构造函数执行
初始化列表只能用于构造函数
初始化列表可以同时初始化多个数据成员初始化列表存在的必要性
我们定义一个类,比如一个圆的类
class Coor { public: Coor() { m_dPi = 3.14; } private: const double m_dPi; }; 上面的那个代码是有错误的,因为const修饰的变量不能改变,然后在构造函数中给变量赋值了,所以就会报错 //这个时候就能体现出我们初始化列表的必要性了 //初始化列表的代码演示: class Coor { public: Coor():m_dPi(3.14){}//m_dPi(3.14) 是初始化的列表,这样就不会再报错了 private: const double m_dPi; };
构造函数
/**
* 定义类:Student
* 数据成员:m_strName
* 无参构造函数:Student()
* 有参构造函数:Student(string _name)
* 拷贝构造函数:Student(const Student& stu)
* 析构函数:~Student()
* 数据成员函数:setName(string _name)、getName()
*/
class Student { public: Student() { m_strName = "jim"; cout << "默认构造函数,调用这个类的时候无需参数就自动调用!" << endl; } Student(string name){ m_strName = name; cout << "需要参数的构造函数!" << endl; } /*Student(string name):m_strName(name){ cout << "初始化列表,数据成员用了const修饰之后必须要用的!" << endl; }*/ /*Student(const string name) { m_strName = name; cout << "拷贝构造函数,在类调用被拷贝的时候调用" << endl; }*/ ~Student() { cout << "系统销毁时自动调用到我了!必须是无参数的,不能重载" << endl; } void setName(string name) { m_strName = name; } string getName() { return m_strName; } private: //const string m_strName; string m_strName; };
this 指针指向被调用的成员函数所属的对象
this 指针是隐含每一个非静态成员函数所属的对象
this不需要定义直接用就可以
this指针的用途
当形参和成员变量同名时,可以用this来解决
在类的非静态成员函数中返回对象本身,return *thisclass Proson { public: Proson(int age) { this->age = age; } int Show() { return age; } Proson& ProsonAdd(Proson& p) { //Proson& p 把一个对象传进来,在这里就可以直接调用这个对象里面的属性了 this->age += p.age; return *this;//返回这个对象的本身,定义函数的返回值必须是Proson&地址 } private: int age;//这个名字和构造函数中的参数同名了,会报错,加上this就指向就可以 解决 }; void test01() { Proson p1(10); cout << p1.Show() << endl; } //return *this void test02() { Proson p1(10); Proson p2(10); //Proson返回这个对象的本身之后,我们就又可以直接的调用这个对象里面的函数成员了 p2.ProsonAdd(p1).ProsonAdd(p1).ProsonAdd(p1); cout << p2.Show() << endl; } int main_this() { test02(); system("pause"); return 0; }
const修饰成员函数
#include <iostream> using namespace std; ///常函数: ///1.成员函数后加上const之后,我们称这个函数为常函数 ///2.常函数内不可以修改成员属性 ///3.成员属性申明时加上mutable,在常函数中依然可以修改 class Proson { public: /* 常函数加上了const之后,也就相当于 const Proson * const this 修饰的是this 这样 this->m_A值也就不能在更改了,指针被修饰,常量也被修饰了,都不能改 */ void ShowProson() const{ //this = NULL; //this是一个指针常量,也就是指向的地址不能改变,指向的值可以改变 m_A = 100;//加上了const之后变成了常函数,就不能这样修改成员属性值了 } mutable int m_B; int m_C; private: //int m_A;//没有给成员属性前面加上mutable,在ShowProson常函数中能修改这个值 mutable int m_A;//特殊变量,即使在常函数中也是可以修改属性值的 }; ///常对象: ///1.对象前加上const之后,叫常对象 ///2.常对象只能调用常函数 void test04() { const Proson p;//常函数 //p.m_C=100; 这个就报错了,因为是一个常对象,只能调用常函数,和加上mutable关键字的成员属性 p.m_B = 100;//必须要在公共区域 p.ShowProson(); } int main03() { system("pause"); return 0; }
类继承,有三种继承方式:public 公共的,protected 受保护的,private 私有的
#include <iostream> #include <string> using namespace std; class Publico { public: void Public_all() { cout << "我是全部的内容" << endl; } }; class Java :public Publico{ public: void Javas() { cout << "Java" << endl; } }; class Python :public Java { public: void Pythons() { cout << "python" << endl; } }; int test() { Java* java = new Java(); Python* python = new Python(); if (java == NULL) { return 0; } if (python == NULL) { return 0; } java->Javas(); java->Public_all(); cout << "*************************" << endl; python->Pythons(); python->Public_all(); cout << "以下是python类调用的" << endl; python->Javas(); delete python; delete java; python = NULL; java = NULL; } int main_() { test(); system("pause"); return 0; }
多态继承
#include <iostream> #include <string> using namespace std; //多继承的菱形多继承问题 //动物类 class Animalia { public: int Age; }; //羊类,继承了动物类 class Sheep:virtual public Animalia { public: int Age; }; //陀类,继承了动物类 class Tuo:virtual public Animalia { public: int Age; }; //羊驼类,继承了陀类和羊类 class Alpaca :public Sheep, public Tuo { public: void print() { //cout << Age << endl;//继承了两个age,就会报错了 //可以使用作用域来解决,但是我们只需要一份数据就行了 //这时候我们可以使用虚继承来解决这个问题 //使用virtual关键词,public为继承方式 //在基类上的语法是 class name:virtual public _name } }; void Alpaca_fun() { Alpaca alp; alp.Sheep::Age = 18; alp.Tuo::Age = 28; //当发生了虚继承之后,他们的数据也就只有一份,取最后赋值 cout << "alp.Sheep::Age = " << alp.Sheep::Age << endl; cout << "alp.Tuo::Age = " << alp.Tuo::Age << endl; } ///多态的虚函数 class Animalia2 { public: virtual void print() { cout << "This is animal" << endl; } }; class Cat:public Animalia2 { public: void print() { cout << "This is Cat" << endl; //当子类重写父类中的函数,子类的虚函数表内部会替换成子类的虚函数地址,也就是覆盖掉了父类中的函数 } }; class Dog :public Animalia2 { public: void print() { cout << "This is Dog" << endl; } }; //当父类的指针或者引用指向子类对象的时候发生多态 void Animalia2_son(Animalia2 & animalia2) //这是一个引用,Animalia2 & animalia2 = dog,父类的引用指向子类dog对象 { animalia2.print(); //1.在基类Animalia基类中的函数没有变成虚函数之前,这里不管是传入的是哪一个对象打印的都是基类中的函数 //没有使用virtual是地址早绑定,在编译阶段确定了函数的地址 //2.如果想要的地址是动态绑定的就在父类中的函数加入virtual关键字,子类可以加野可以不加 //定义了父类中加上virtual之后,子类中相同函数就发生了重写 } int main_0() { Dog dog; Cat cat; Animalia2_son(dog); //Alpaca_fun(); system("pause"); return 0; }