类中成员(Class Member)
- 属性(成员变量)
- 方法(成员函数)
- 类型
内部类:也称嵌套类
类中(匿名)枚举类型的作用:可以将其枚举元素作为类级常量使用(简单场合下(整型)),相比静态常量更方便。非静态常属性只是对象级常量。
属性也可以为引用成员,注意其初始化语法。
对象数组(Object Array)
数组元素为对象(类类型的数据)
设计模式(Design Mode)
常用设计模式:单例模式、工厂模式、观察者模式、代理模式等。
单例模式的实现。
继承(Inheritance)
在某个已存在的类的基础上创建一个新的类。这个已存在的类称为父类或基类,新类称为子类或派生类。
子类继承父类,父类派生出子类。
子类会无条件获得父类的几乎所有成员。 并可以在此基础上新增成员,当然也可以改进从父类继承的成员(同名覆盖)。
同名覆盖:子类中的某个属性或方法与父类中的同名。(属性名或方法名相同即可,方法的形参不用相同)
三种继承方式:
- public:公有继承,父类中的公有和保护成员在子类中的访问权限保持不变,私有成员在子类中不可访问(不可见)。
- protected:保护继承,父类中的公有和保护成员在子类中的访问权限都为保护的,私有成员在子类中不可访问(不可见)。
- private:私有继承,父类中的共有和保护成员在子类中的访问权限都变为私有的,私有成员在子类中不可访问(不可见)。
默认继承方式为私有继承。
公有继承最常用,因为这种继承方式可以使父类成员的访问权限不会因为继承而发生改变。
继承关系就是一种 ”IS A“ 的关系
构造函数、析构函数、友元不会被子类继承。
创建子类对象时,先执行父类构造函数,然后执行子类构造函数。默认是执行父类的无参构造函数,但可以在子类的构造函数参数初始化列表中显式指定调用父类中的某个构造函数。
子类对象销毁时,先执行子类的析构函数,再执行父类的析构函数。
单继承
一个类的直接父类只有一个。
多级继承
具有两层或更多层继承关系。
直接父类、直接子类
间接父类、简介子类
类图画法
多(重)继承
也称为多继承,一个类的直接父类可以有多个。
在实际项目开发中,尽量少用!
构造函数的执行顺序为:子类定义时父类引用的顺序(从左到右),析构函数的执行顺序相反;
例如
//声明三个类
class A;
class B;
class C:public A, public B;
//定义一个C类的对象,其构造函数调用的顺序为:A、B、C ,析构函数调用的顺序为C、B、A;
菱形继承问题:同一个类通过多条继承路径派生出一个间接子类,那么该类中的所有成员在这个间接子类中将会有多份,这将会浪费存储空间并且毫无意义。
虚继承(Virtual Inheritance)
虚基类(Virtual Base Class)
只能由虚基类构造函数负责对从虚基类继承的所有属性进行初始化。
virtual关键字避免菱形继承问题,但是virtual也会占用一小段空间来记录相同的继承属性,对于小型类的继承,加上virtual关键字也许会使对象更大。(Virtual关键字加载菱形类声明时继承的直接父类前)<只能由虚基类构造函数负责对从虚基类继承的所有属性进行初始化>。
同时加上virtual关键字,能够在构造函数初始化时,调用虚基类的属性,尽管直接继承也有相同属性,但是会交给虚基类负责,调用虚基类的构造函数,若直接父类同时也给此属性初始化,会不起作用。
实例一:类中成员
#include <iostream>
using namespace std;
class A
{
public: // 私有与公有,作用于 类中与类外
int i;
int& j = i;
A():j(i)
{
}
typedef unsigned int u32;
struct Book
{
int isbn;
float price;
};
enum Sex
{
// 枚举常量或枚举元素
WOMAN = 3,
MAN
};
// 匿名枚举类型
enum {MON, TUE, WED, THU, FRI, SAT, SUN};
private:
// 嵌套类或内部类 子类可以访问父类的所有
class B
{
private:
int b;
};
void show()
{
B b2;
// b2.b = 5;
u32 n;
Book b;
}
};
int main()
{
A::u32 n1;
A::Book b1;
A::Sex s = A::MAN;
int i = A::MON;
n1 = 50;
b1.isbn = 10003;
// A::B b3;
// b3.b = 5;
return 0;
}
实例二:单例模式
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
int sno;
string name;
static Student* s;
Student():sno(1001), name("张三")
{
}
public:
static Student& create()
{
if(nullptr == s)
{
s = new Student;
}
return *s;
}
void setName(string name)
{
this->name = name;
}
void show()
{
cout << sno << " " << name << endl;
}
};
Student* Student::s = nullptr;
int main()
{
Student& s1 = Student::create();
Student& s2 = Student::create();
s2.setName("李四");
s1.show();
return 0;
}
实例三:对象数组
#include <iostream>
#include <cstring>
using namespace std;
class Student
{
private:
int sno = 0;
string name = "";
public:
Student()
{
cout << "Student()" << endl;
}
Student(int sno,string name):sno(sno), name(name)
{
cout << "Student(int, String)" << endl;
}
void show()
{
cout << sno << " " << name << endl;
}
};
int main()
{
//栈区对象
Student stus1[5] {{1001, "张三"},{1002, "李四"}}; //栈区定义
//堆区对象
Student *stus2 = new Student[5]{{1001, "张三"},{1002, "李四"}}; //堆区定义
delete[] stus2;
return 0;
}```
实例四:单一继承
```c
#include <iostream>
using namespace std;
class A
{
private:
int k;
public:
int i;
typedef int dj;
void show()
{
cout << "嗨害!" << endl;
}
};
class B
{
};
class C:public A
{
public:
int j;
int i; //属性同名覆盖
void speak()
{
cout << "我还可以说话!" << endl;
}
typedef float dj; //类型同名覆盖
//方法同名覆盖
void show(int i)
{
cout << "嗨嗨害!" << endl;
}
};
int main()
{
C c;
c.i = 3;
//c.show(1);
C::dj j = 5;
c.speak();
B b;
c.A::i = 7;
cout << sizeof(c) <<endl;
return 0;
}
实例五:多级继承
#include <iostream>
#include <string>
using namespace std;
class Person
{
private:
int id;
string name;
public:
Person();
Person(int id, string name);
~Person();
friend void show();
};
class Chinese: public Person
{
private:
string shengXiao;
public:
Chinese();
Chinese(int id, string name, string shengXiao);
~Chinese();
friend void show();
};
class Wuhaner: public Chinese
{
public:
Wuhaner();
Wuhaner(int id, string name, string shengXiao);
~Wuhaner();
};
Person::Person()
{
cout << "Person()" << endl;
}
Person::Person(int id, string name):id(id), name(name)
{
cout << "Person(int, string)" << endl;
}
Person::~Person()
{
cout << "~Person()" << endl;
}
Chinese::Chinese()
{
cout << "Chinese()" << endl;
}
Chinese::Chinese(int id, string name, string shengXiao): Person(id, name), shengXiao(shengXiao)
{
cout << "Chinese(int, string, string)" << endl;
}
Chinese::~Chinese()
{
cout << "~Chinese()" << endl;
}
Wuhaner::Wuhaner()
{
cout << "Wuhaner()" << endl;
}
Wuhaner::Wuhaner(int id, string name, string shengXiao): Chinese(id, name, shengXiao)
{
cout << "Wuhaner(int, string, string)" << endl;
}
Wuhaner::~Wuhaner()
{
cout << "~Wuhaner()" << endl;
}
void show()
{
Person a;
a.id = 2000;
Chinese c;
c.shengXiao = "虎";
}
int main()
{
// Chinese c1;
// Person p1;
// Chinese c2(1001, "张三", "龙");
Wuhaner w;
return 0;
}