C++笔记汇总3 类和对象
类和对象
1、封装
设计一个圆类,求圆的周长
1 2 3 4 5 6 7 8 9 #define PI 3.14 class Circle { public : int r; double calc () { return 2 * PI * r; } };
三种权限
公共权限 public 成员类内可以访问,类外可以访问
保护权限 protected
成员类内可以访问,类外不可以访问,继承中儿子可以访问父亲权限 私有权限
private 成员类内可以访问,类外不可以访问,继承中儿子可以不访问父亲权限
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Person { public : string m_Name; protected : string m_Car; private : int m_Password; public : void fun () { m_Name = "张三" ; m_Car = "拖拉机" ; m_Password = 123456 ; } private : void fun2 () { m_Name = "张三" ; m_Car = "拖拉机" ; m_Password = 123456 ; } };
struct 和 class 的区别
struct 默认的权限为 公共 public
class 默认的权限为 私有 private
1 2 3 4 5 6 class C1 { int m_A; }; struct C2 { int m_A; };
2.对象的初始化和清理
1. 构造函数
没有返回值
函数名和类名相同
构造函数可以有参数,可以发生重载
创建对象的时候,构造函数自动调用一次,而且仅调用一次
2. 析构函数
没有返回值
函数名和类名相同
无参数,不能发生重载
对象销毁前自动调用,且仅调用一次
构造和析构都是必须有的实现,如果我们自己不提供,编译器会自动提供一个空实现的构造和析构
1 2 3 4 5 6 7 8 9 10 class Person1 { public : Person1 () { cout << "Person1函数的调用" << endl; } ~Person1 () { cout << "~Person1函数的调用" << endl; } }; void test01 () { Person1 p1; }
构造函数的分类及调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 class Person2 { public : int age; Person2 () { cout << "Person2函数调用" << endl; } Person2 (int a) { age = a; cout << a << endl; } Person2 (const Person2& p) { age = p.age; cout << age << endl; } ~Person2 () { cout << "~Person2函数调用" << endl; } }; void test02 () { Person2 p1; Person2 p2 (10 ) ; Person2 p3 (p2) ; Person2 p4 = Person2 (10 ); Person2 p5 = Person2 (p4); Person2 (10 ); Person2 p6 = 10 ; } class Person3 { public : int age; Person3 () { cout << "Person3函数的调用" << endl; } Person3 (int age) { this ->age = age; cout << "Person3函数的调用" << endl; } Person3 (Person3& p) { this ->age = p.age; cout << "Person3函数的调用" << endl; } ~Person3 () { cout << "~Person3函数的调用" << endl; } }; void do_work (Person3 p) { p.age = 10 ; } Person3 do_work2 () { Person3 p (10 ) ; return p; } void test03 () { Person3 p1 (20 ) ; Person3 p2 (p1) ; Person3 p4; do_work (p4); }
如果用户定义有参构造函数,c++不再提供默认无参构造,但是会提供默认拷贝构造
如果用户定义拷贝构造函数,c++不会再提供其他构造函数
深拷贝和浅拷贝
浅拷贝:简单复制拷贝操作
深拷贝:在堆区重新申请空间,进行拷贝构造
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Person4 { public : Person4 () { cout << "Person4函数的调用" << endl; } Person4 (int age, int height) { this ->age = age; this ->height = new int (height); } Person4 (const Person4& p) { this ->age = p.age; this ->height = new int (*p.height); cout << "Person4拷贝构造函数调用" << endl; } ~Person4 () { if (this ->height != NULL ) { delete this ->height; this ->height = NULL ; } cout << "~Person4函数的调用" << endl; } int age; int * height; }; void test04 () { Person4 p1 (18 , 160 ) ; Person4 p2 (p1) ; }
初始化列表
1 2 3 4 5 6 7 8 9 10 11 12 class Person5 { public : int a, b, c; Person5 (int a, int b, int c) : a (a), b (b), c (c) {} };
Static
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Person6 { public : static int a; private : static int b; }; int Person6::a = 100 ; int Person6::b = 200 ;void test06 () { Person6 p1; cout << p1.a << endl; Person6 p2; p2.a = 200 ; cout << p1.a << endl; Person6 p3; cout << p3.a << endl; cout << Person6::a << endl; } class Person7 { public : static void func () { a = 100 ; cout << "static void fun的调用" << endl; } static int a; int b; private : static void fun2 () { cout << "static void fun2调用" << endl; } }; int Person7::a;void test07 () { Person7 p1; p1.func (); Person7::func (); }
成员对象和成员函数分开存储
1 2 3 4 5 6 7 8 9 10 11 class Person1 { int a; static int b; void func () {} static void func2 () {} }; int Person1::b;void test01 () { Person1 p; cout << sizeof (p) << endl; }
Summary:
1.空对象默认字节为 1,若非空则不占字节
2.非静态变量属于类的对象,占用字节空间
3.静态变量不属于类的对象,不占用字节空间
4.静态函数不属于类的对象,不占用字节空间
5.非静态函数不属于类的对象,不占用字节空间
this指针作用:
1.解决名称冲突
2.返回对象本身用*this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 class Person2 { public : int age; Person2 (int age) { this ->age = age; } Person2& PersonAddAge (Person2& p) { this ->age += p.age; return *this ; } }; void test02 () { Person2 p1 (10 ) ; Person2 p2 (20 ) ; p1.PersonAddAge (p2).PersonAddAge (p2); cout << p1.age << endl; } class Person3 { public : void showClassName () { cout << "this is Person3 class" << endl; } void showPersonAge () { cout << "age=" << age << endl; } int age; }; void test03 () { Person3* p = NULL ; p->showClassName (); }
const修饰成员函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 class Person4 { public : void showPerson () const { this ->b = 100 ; } void fun () { a = 10 ; } int a; mutable int b; }; void test04 () { }
友元
1.全局函数做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Building { friend void goodGay (Building& building) ; public : string m_SittingRoom; Building () { m_SittingRoom = "客厅" ; m_BedRoom = "卧室" ; } private : string m_BedRoom; }; void goodGay (Building& building) { cout << "visit" << building.m_SittingRoom << endl; cout << "visit" << building.m_BedRoom << endl; } void demo1 () { Building building; goodGay (building); }
2.类做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 class Building2 ; class GoodGay { public : GoodGay (); void visit () ; Building2* building; }; class Building2 { friend class GoodGay ; public : Building2 (); string m_SittingRoom; private : string m_BedRoom; }; GoodGay::GoodGay () { building = new Building2; }; void GoodGay::visit () { cout << "visit" << building->m_SittingRoom << endl; cout << "visit" << building->m_BedRoom << endl; } Building2::Building2 () { m_SittingRoom = "客厅" ; m_BedRoom = "卧室" ; } void demo2 () { GoodGay gg; gg.visit (); }
3.成员函数做友元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Building3 ; class GoodGay1 { public : GoodGay1 (); void visit () ; void visit2 () ; Building3* building; }; class Building3 { friend void GoodGay1::visit () ; public : Building3 (); string m_SittingRoom; private : string m_BedRoom; }; GoodGay1::GoodGay1 () { building = new Building3; }; void GoodGay1::visit () { cout << "visit" << building->m_SittingRoom << endl; cout << "visit" << building->m_BedRoom << endl; } void GoodGay1::visit2 () { cout << "visit2" << building->m_SittingRoom << endl; } Building3::Building3 () { m_SittingRoom = "客厅" ; m_BedRoom = "卧室" ; } void demo3 () { GoodGay1 gg; gg.visit (); }
3.运算符重载
一.加法运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class Person1 { public : int a, b; Person1 operator +(Person1& p) { Person1 tmp; tmp.a = this ->a + p.a; tmp.b = this ->b + p.b; return tmp; } }; Person1 operator -(Person1& p1, Person1& p2) { Person1 tmp; tmp.a = p1.a - p2.a; tmp.b = p1.b - p2.b; return tmp; } Person1 operator +(Person1& p1, int num) { Person1 tmp; tmp.a = p1.a + num; tmp.b = p1.b + num; return tmp; } void test01 () { Person1 p1; p1.a = 10 ; p1.b = 20 ; Person1 p2; p2.a = 30 ; p2.b = 40 ; Person1 p3 = p1 + p2; Person1 p4 = p1 - p2; cout << "p3.a:" << p3.a << "\np3.b:" << p3.b << endl; cout << "p4.a:" << p4.a << "\np4.b:" << p4.b << endl; Person1 p5 = p1 + 10 ; cout << "p5.a:" << p5.a << "\np5.b:" << p5.b << endl; }
二.左移运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Person2 { friend ostream& operator <<(ostream& out, Person2& p); public : void setA (int a) { this ->a = a; } void setB (int b) { this ->b = b; } private : int a, b; }; ostream& operator <<(ostream& out, Person2& p) { out << "p.a:" << p.a << endl; out << "p.b:" << p.b << endl; return out; } void test02 () { Person2 p; p.setA (10 ); p.setB (20 ); cout << p << endl; }
三.递增运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class MyInteger { friend ostream& operator <<(ostream& out, MyInteger my); public : MyInteger () { num = 0 ; } MyInteger& operator ++() { ++num; return *this ; } MyInteger operator ++(int ) { MyInteger tmp = *this ; ++num; return tmp; } private : int num; }; ostream& operator <<(ostream& out, MyInteger my) { out << my.num; return out; } void test03 () { MyInteger my; cout << ++my << endl; cout << my++ << endl; }
四.赋值运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 class Person4 { public : Person4 (int age) { this ->age = new int (age); } ~Person4 () { if (this ->age != NULL ) { delete this ->age; this ->age = NULL ; } } Person4& operator =(Person4& p) { if (this ->age != NULL ) { delete this ->age; this ->age = NULL ; } this ->age = new int (*p.age); return *this ; } int * age; }; void test04 () { Person4 p1 (18 ) ; Person4 p2 (20 ) ; Person4 p3 (30 ) ; cout << "p1年龄为" << *p1.age << endl; cout << "p2年龄为" << *p2.age << endl; cout << "p3年龄为" << *p3.age << endl; p2 = p1 = p3; cout << "p1年龄为" << *p1.age << endl; cout << "p2年龄为" << *p2.age << endl; cout << "p3年龄为" << *p3.age << endl; }
五.关系运算符重载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Person5 { public : string name; int age; Person5 (string name, int age) { this ->age = age; this ->name = name; } bool operator ==(Person5& p) { if (this ->age == p.age && this ->name == p.name) { return true ; } return false ; } bool operator !=(Person5& p) { if (this ->age == p.age && this ->name == p.name) { return false ; } return true ; } }; void test05 () { Person5 p1 ("Tom" , 18 ) ; Person5 p2 ("Tom" , 18 ) ; if (p1 == p2) { cout << "p1==p2" << endl; } else { cout << "p1!=p2" << endl; } }
六.函数调用运算符()重载[仿函数]
1 2 3 4 5 6 7 8 9 10 11 12 class MyPrint { public : void operator () (string test) { cout << test << endl; } }; void MyPrint02 (string test) { cout << test << endl; } void test06 () { MyPrint my; my ("hello world" ); MyPrint02 ("hello world" ); }
4.继承
继承的好处:
1.减少重复代码
2.子类也成为派生类,父类也称基类
语法:class子类:继承方式 父类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class BasePage { public : void header () { cout << "头部" << endl; } void footer () { cout << "脚部" << endl; } void left () { cout << "左侧" << endl; } }; class Java : public BasePage { public : void content () { cout << "Java内容" << endl; } }; class Python : public BasePage { public : void content () { cout << "Python内容" << endl; } }; void test01 () { Java ja; ja.header (); ja.footer (); ja.left (); ja.content (); Python py; py.header (); py.footer (); py.left (); py.content (); }
三种继承方式 优先级public>protected>private
公共继承
保护继承
私有继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 class Base1 { public : int a; protected : int b; private : int c; }; class Son1 : public Base1 { public : void fun () { a = 10 ; b = 20 ; } }; class Son2 : protected Base1 { public : void fun () { a = 10 ; b = 20 ; } }; class Son3 : private Base1 { public : void fun () { a = 10 ; b = 20 ; } }; class GrandSon3 : public Son3 { public : void func () { } }; void test02 () { Son1 s1; s1.a = 100 ; Son2 s2; Son3 s3; }
继承中的对象模型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Base3 { public : int a; protected : int b; private : int c; }; class Son4 : public Base3 { public : int d; }; void test03 () { cout << "sizeof(Son4):" << sizeof (Son4) << endl; }
继承中的构造和析构顺序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Base4 { public : Base4 () { cout << "Base4-begin" << endl; } ~Base4 () { cout << "Base4-end" << endl; } }; class Son5 : public Base4 { public : Son5 () { cout << "Son5-begin" << endl; } ~Son5 () { cout << "Son5-end" << endl; } }; void test04 () { Son5 s; }
继承中同名成员处理方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 class Base5 { public : Base5 () { a = 10 ; } void func () { cout << "Base5-func()" << endl; } void func (int a) { cout << "Base5-func(" << a << ")" << endl; } int a; }; class Son6 : public Base5 { public : Son6 () { a = 100 ; } void func () { cout << "Son6-func()" << endl; } int a; }; void test05 () { Son6 s; cout << s.a << endl; cout << s.Base5::a << endl; s.func (); s.Base5::func (); s.Base5::func (100 ); } class Base6 { public : Base6 () { a = 10 ; } static void func () { cout << "Base6-func()" << endl; } static void func (int a) { cout << "Base6-func(" << a << ")" << endl; } static int a; }; int Base6::a = 10 ;class Son7 : public Base6 { public : Son7 () { a = 100 ; } static void func () { cout << "Son7-func()" << endl; } static int a; }; int Son7::a = 100 ;void test06 () { Son7 s; cout << s.a << endl; cout << s.Base6::a << endl; cout << Son7::a << endl; cout << Son7::Base6::a << endl; s.func (); s.Base6::func (); s.Base6::func (100 ); Son7::func (); Son7::Base6::func (); Son7::Base6::func (100 ); }
多继承语法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Base7 { public : Base7 () { a = 10 ; } int a; }; class Base8 { public : Base8 () { a = 100 ; } int a; }; class Son8 : public Base7, public Base8 { public : Son8 () { c = 200 ; d = 300 ; } int c, d; }; void test07 () { Son8 s; cout << "sizeof(s)" << sizeof (s) << endl; cout << "s.Base7::a" << s.Base7::a << endl; cout << "s.Base8::a" << s.Base8::a << endl; } class Animal { public : int age; }; class Sheep : virtual public Animal {};class Tuo : virtual public Animal {};class YangTuo : public Sheep, public Tuo {};void test08 () { YangTuo y; y.Sheep::age = 18 ; y.Tuo::age = 28 ; cout << y.Sheep::age << endl; cout << y.Tuo::age << endl; cout << y.age << endl; }
5.多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Animal { public : virtual void speak () { cout << "speaking" << endl; } }; class Cat : public Animal { public : void speak () { cout << "Cat-speaking" << endl; } }; class Dog : public Animal { public : void speak () { cout << "Dog-speaking" << endl; } }; void do_speak (Animal& animal) { animal.speak (); }
动态多态满足条件:
1.有继承关系
2.子类重写父类的虚函数
动态多态使用
父类的指针或者引用执行子类对象
1 2 3 4 5 6 7 void test01 () { Cat cat; Dog dog; do_speak (cat); do_speak (dog); cout << sizeof (Animal); }
纯虚函数和抽象类
纯虚函数语法:
当类中含有纯虚函数,则这个类为抽象类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 class Base { public : virtual void func () = 0 ; }; class Son : public Base { public : void func () { cout << "Son-func()" << endl; } }; void test02 () { Son s; s.func (); Base* base = new Son; base->func (); } class Animal1 { public : Animal1 () {} virtual void speak () = 0 ; virtual ~Animal1 () = 0 ; }; Animal1::~Animal1 () { cout << "纯虚析构" << endl; } class Cat1 : public Animal1 { public : Cat1 (string name) { this ->name = new string (name); } void speak () { cout << *name << " Cat1-speaking" << endl; } ~Cat1 () { if (this ->name != NULL ) { delete this ->name; this ->name = NULL ; } } string* name; }; void test03 () { Animal1* animal = new Cat1 ("Tom" ); animal->speak (); delete animal; }
Summary:
1.虚析构或纯虚析构就是用来解决通过父类指针释放子类对象
2.如果子类没有堆区数据,可以不写为虚析构或纯虚析构
3.拥有纯虚析构函数的类是抽象类