目录
面向对象的三大特征:封装,继承,多态
封装:封装是把客观事物抽象成类,并且把自己的属性和方法让可信的类或对象操作,对不可性的隐藏。
继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
多态:允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。这就意味着虽然针对不同对象的具体操作不同,但通过一个公共的类,它们(那些操作)可以通过相同的方式予以调用。
继承的基本形式:
- class 子类 继承权限 基类
- {
- };
若未写继承权限,则默认是私有继承(一般不写私有继承)
- class A
- {
- public:
- int m_i;
- void Print()
- {
- cout << "A::print" << endl;
- }
- protected:
- int m_j;
- private:
- int m_k;
- };
- class B :A//默认是私有的继承
- {
-
- };
我们知道构造函数和析构函数是跟对象的创建与消亡的善后工作相关。我们所创建派生类的对象,虽然和基类的对象有相同之处,但是仍然是不同的对象。所以,适用于基类的构造函数和析构函数不可能完全满足派生类对象的创建和消亡的善后工作。因此,构造函数和析构函数不被继承。
如下所示:worker类是从Person继承而来,大小为8 。
- class Person
- {
- public:
- Person(int num = 1000) :m_num(num) {}
- void print()
- {
- cout << "count = " << m_count << endl;
- }
- protected:
- int m_num;
- static int m_count;
- };
- int Person::m_count;
- class Student :public Person
- {
- public:
- Student(int num, const char* job) :Person(num)
- {
- m_job = new char[strlen(job) + 1];
- strcpy_s(m_job, strlen(job) + 1, job);
- m_count++;
- }
- private:
- char* m_job;
- };
- class Teacher :public Person
- {
- public:
- Teacher(int num,const char*job):Person(num)
- {
- m_job = new char[strlen(job) + 1];
- strcpy_s(m_job, strlen(job) + 1, job);
- m_count++;
- }
- private:
- char* m_job;
- };
- class Worker :public Person
- {
- public:
- Worker(int num,const char*job) :Person(num)
- {
- m_job = new char[strlen(job) + 1];
- strcpy_s(m_job, strlen(job) + 1, job);
- m_count++;
- }
- private:
- char* m_job;
- };
- void main()
- {
- Student s(1001, "student");
- Teacher t(1002, "teacher");
- Worker w(1003, "worker");
- w.print();
- s.print();
- Worker w1(1006, "worker");
- s.print();
- cout << sizeof(Worker) << endl;//8
- }
| 基类的权限: | public | protected | private |
| public | pubic | protected | private |
| protected | protected | protected | private |
| private | 不可访问 | 不可访问 | 不可访问 |
- class A
- {
- public:
- int m_i;
- void Print()
- {
- cout << "A::print" << endl;
- }
- protected:
- int m_j;
- private:
- int m_k;
- };
- class B :public A//全部继承A
- {
- public:
- void set()
- {
- m_i = 20;
- m_j = 30;
- //m_k = 40;//私有的能被继承,不能被访问
- }
- };
- class C :protected A
- {
- public:
- void test()
- {
- m_i = 14;
- m_j = 13;
- //m_k = 12;//私有的能被继承,不能被访问
- }
- };
- class D :private A
- {
- public:
- void test()
- {
- m_i = 10;
- m_j = 12;
- //m_k = 14;//私有的能被继承,不能被访问
- }
- }
- class DD :public D
- {
- public:
- void ff()
- {
- //A的public和protected属性被D私有化
- m_i = 1;
- m_j = 2;
- m_k = 3;//
- }
- };
外界无法访问protected和private成员
- class A
- {
- public:
- int m_i;
- void Print()
- {
- cout << "A::print" << endl;
- }
- protected:
- int m_j;
- private:
- int m_k;
- };
- class B :public A//全部继承A
- {
- public:
- void set()
- {
- m_i = 20;
- m_j = 30;
- //m_k = 40;//私有的能被继承,不能被访问
- }
- };
- class C :protected A
- {
- public:
- void test()
- {
- m_i = 14;
- m_j = 13;
- //m_k = 12;//私有的能被继承,不能被访问
- }
- };
- void main()
- {
- cout << sizeof(B) << endl;
- B b;
- b.Print();
- b.m_i = 12;
- //b.m_j = 8;
- //b.m_k = 13;//外界不能使用
-
- C c;
- //C将属性m_i变成protected
- c.m_i = 12;
- c.m_j = 13;
- c.m_k = 14;//被C保护继承
- }
1、除构造析构全盘接收
2、改写
3、添加子类特有的
- class A
- {
- public:
- A() { cout << "A" << endl; }
- void print() { cout << "A::print" << endl; }
- ~A() { cout << "~A" << endl; }
- private:
- int m_i;
- };
- class B :public A
- {
- public:
- B() { cout << "B" << endl; }
- ~B() { cout << "~B" << endl; }
- private:
- int m_j;
- };
- void main()
- {
- B b;//A b
- }
先调用基类A的构造函数,将所派生下来的数据成员先行构造,再调用B的构造函数;先析构B,再析构A。
1、先按照继承顺序调用基类的构造
2、按照组合顺序调用组合的构造
3、调用自己的构造
- class CPU
- {
- public:
- CPU() { cout << "CPU" << endl; }
- };
- class KB
- {
- public:
- KB() { cout << "KB" << endl; }
- };
- class Mouse
- {
- public:
- Mouse() { cout << "Mouse" << endl; }
- };
- class Computer
- {
- public:
- Computer() { cout << "Computer" << endl; }
- private:
- CPU cpu;
- KB kb;
- Mouse ms;
- };
- class Touch
- {
- public:
- Touch() { cout << "Touch" << endl; }
-
- };
- class Laptop :public Computer
- {
- public:
- Laptop() { cout << "Laptop" << endl; }
- private:
- Touch tc;
- };
- void main()
- {
- Laptop lt;
- }
派生类的成员函数和基类的函数同名同参,则将基类的函数隐藏
- class A
- {
- public:
- void print() { cout << "A::print" << endl; }
- protected:
- int m_i;
- };
- class B :public A
- {
- public:
- //print将派生下来的A的print隐藏了
- void print()
- {
- cout << "B::print" << endl;
- cout << m_i << " " << A::m_i << endl;
- }
- void set() { m_i = 10; A::m_i = 20; }
- protected:
- int m_i;
- };
- void main()
- {
- A a;
- B b;
- a.print();
- b.set();
- b.A::print();//利用b调用A的成员函数
- b.print();
- cout << sizeof(B) << endl;
- }
- class Person
- {
- public:
- Person(int num,const char *name ,char sex):m_num(num), m_sex(sex)
- {
- int len = strlen(name) + 1;
- m_name = new char[len];
- strcpy_s(m_name, len, name);
- }
- Person(Person& p) :m_num(p.m_num), m_sex(p.m_sex)//拷贝构造
- {
- m_name = new char[strlen(p.m_name) + 1];
- strcpy_s(m_name, strlen(p.m_name)+1, p.m_name);
- }
- ~Person()
- {
- delete[]m_name;
- m_name = NULL;
- }
- void Show()
- {
- cout << m_num << m_name << m_sex << endl;
- }
- private:
- int m_num;
- char* m_name;
- char m_sex;
- };
- class Student :public Person
- {
- public:
- Student(int num, const char* name, char sex,float score):Person(num,name,sex),m_score(score)
- {
-
- }
- ~Student()
- {
-
- }
- Student(Student& s) :Person(s)//拷贝构造
- {
- m_score = s.m_score;
- }
- void print()
- {
- Show();
- cout << m_score << endl;
- }
- private:
- float m_score;
- };
- void main()
- {
- Student s1(1001, "tianpangpang", 'f', 89);
- s1.print();
- Student s2(s1);
- s2.print();
- }
1、程序设计者在基类和派生类中都没有重载operator=函数; C++编译器将在基类和派生类中自动产生按位赋值的,重载operator=函数;C++编译器会在派生类的重载赋值函数中,加入基类重载赋值函数的调用,是C++编译器合成的代码;(完成行为的统一);
2、程序设计者在基类中定义重载赋值函数;而在派生类中没有定义重载赋值函数;C++编译器将会在派生类中自动产生按位赋值的重载赋值函数。并合成代码,调用(关联)基类的重载赋值函数。
3、程序设计者在基类和派生类中都定义了重载赋值函数;程序设计者在派生类中,没有指定调用基类的重载赋值函数时。C++编译器不会合成调用基类的重载赋值函数的代码。要在派生类的重载赋值函数调用基类的重载赋值函数,程序设计者必须自己加入调用代码。
4、程序设计者在基类中没有定义重载赋值函数(C++编译器将自动产生按位赋值的重载赋值函数)。而在派生类中定义了重载赋值函数。程序设计者在派生类中,没有指定调用基类的重载赋值函数。C++编译 器不会合成调用基类的重载赋值函数的代码。
实现拷贝构造和赋值重载:
- class Person
- {
- public:
- Person():m_sex('f'),m_age(20)
- {
- m_name = new char[1];
- *m_name = '\0';
- cout << "Person()" << endl;
- }
- Person(const char* name, char sex, int age):m_sex(sex),m_age(age)
- {
- m_name = new char[strlen(name) + 1];
- strcpy_s(m_name, strlen(name) + 1, name);
- }
- Person(Person& p) :m_sex(p.m_sex), m_age(p.m_age)
- {
- m_name = new char[strlen(p.m_name) + 1];
- strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
- }
- Person& operator=(Person& p)
- {
- if (this == &p)
- return *this;
- delete[]m_name;
- m_name = new char[strlen(p.m_name) + 1];
- strcpy_s(m_name, strlen(p.m_name) + 1, p.m_name);
- m_sex = p.m_sex;
- m_age = p.m_age;
- return *this;
- }
- void print()
- {
- cout << m_name << " " << m_sex << " " << m_age << " ";
- }
- ~Person()
- {
- if (m_name != NULL)
- {
- delete[]m_name;
- m_name = NULL;
- }
- }
- private:
- char* m_name;
- char m_sex;
- int m_age;
- };
- class Student :public Person
- {
- public:
- Student():m_num(0),m_score(0) { cout << "Student()" << endl; }
- Student(int num, const char* name, char sex, int age, int score):m_num(num),Person(name,sex,age),m_score(score) {}
- void print()
- {
- cout << m_num << " ";
- Person::print();
- cout << m_score << endl;
- }
- Student(Student& s) :Person(s), m_num(s.m_num), m_score(s.m_score) {}
- Student& operator=(Student& s)
- {
- if (this == &s)
- return *this;
- Person::operator=(s);
- m_num = s.m_num;
- m_score = s.m_score;
- return *this;
- }
- private:
- int m_num;
- int m_score;
- };
- void main()
- {
- Student s;
- Student s1(1001, "zhangsan", 'f', 20, 78);
- s.print();
- s1.print();
- Student s2(s1);
- s2.print();
- s = s1;
- s.print();
- }