C++老生常谈的东西:类
具有的特点:抽象、封装、继承和派生、多态
一些个人理解:
我们在说 “球” 的时候就是一个抽象概念,无论你是拿着一个素描的球(实际是石膏球),还是“我们去打球”(一般舍友喊你去打篮球),我们能指向出具体的球,这个是我们从抽象概念继承出来的一个派生类,而 “球” 本身是一个抽象的概念。
封装的情况类似与日常生活中,我们使用手机(或者其他电器等)我们不需要指导内部的电路结构,只用知道基本的开机等操作就可以正常使用了。
多态的一种形象解释,例如说球可以打,球可以踢,我们用球这一抽象类的指针,指向了篮球,那我们就可以利用虚函数的形式(从语境和习惯引出的“虚”意),从基类的球(指针),调用到派生类(篮球)的打的动作。
常对象
常对象用const修饰
class A
{
int a;
void getA() const;//只能引用本类的数据成员,不能进行数据成员的修改
void getB();
};
const A ca;//<只能调用常成员函数,不能调用普通成员函数
常对象类似于普通的常变量,无法进行修改,且必须进行初始化。
常对象中的数据成员可以在构造函数初始化表中进行初始化。
赋值和复制
class A;
A a1, a2;
a1 = a2;//<<这里是赋值
A c1 = a1;//<这里是复制
A c2(a2);//<这里是复制
实际上最本质的区别在于
赋值,需要有两个对象;而复制,是从一个对象复制到一个新的对象中去。
上述表明复制的部分 A c1 = a1; 实际上隐式调用了复制构造函数,实现了新的c1的类的构建。
一般的复制构造函数,编译系统会默认提供,也可以自己进行定义。
静态成员函数
在类中定义的
class A{
...
static int value();
};
属于静态成员函数,这一静态成员函数,由前面C++学习记录(二) 存储期和关键字,是在编译期就在静态区分配好了入口地址,因而没有类的this指针,无法调用到类具体对象的成员,只能调用静态数据成员。
友元friend
快进来我的朋友,在火炉旁找个地方随便坐
class Date;
class Time
{
public:
int second;
void print(Date &d1);
};
class Date
{
public:
friend Time;
private:
int month;
int dat;
int year;
};
void Time::print(Date &d1)
{
cout << second << d1.month << endl;
}
Time作为Date邀请的朋友,可以随便访问他私有的东西
友元这一概念经常用在运算符重载中的双目运算符上,因为一般的运算中需要有两个输入值,而比对的值可能类别不同等。
继承的二义性和虚继承
class A
{
public:
int a;
void display(){ cout << a << endl;}
};
class B
{
public:
int b;
void display(){ cout << b << endl;}
};
class C:public A, public B
{
};
C c1;
//c1.display();//<这里具有二义性
c1.A::display();//调用A的display
c1.B::display();//调用B的display
而虚继承的情况
class N
{
public:
N(int num):n(num)
{}
int n;
};
class A : virtual public N
{
public:
A(int n):N(n)
{}
int a;
void display(){ cout << a << endl;}
};
class B : virtual public N
{
public:
B(int n):N(n)
{}
int b;
void display(){ cout << b << endl;}
};
class C:public A, public B
{
public:
C(int n):A(n), B(n), N(n)
{}
};
最后C类在继承时,需要实现对于基类的初始化,还需要实现虚基类N的初始化,忽略A、B在构造时对N类的初始化。
静态多态和动态多态
静态多态:函数重载、运算符重载,要求在编译时知晓信息,又叫编译多态
动态多态:在程序运行时,动态确定操作对象,一般通过虚函数实现
例如:
class A
{
public:
A(int n){ a = n;}
int a;
virtual void display(){cout << a;}
};
class B : public A
{
public:
B(int n, int m):A(n){ b = m;}
int b;
virtual void display(){cout << b;}
};
int main()
{
B b(3, 4);
A a1(5);
A *p_a;
p_a = &a1;
p_a->display();
p_a = &b;
p_a->display();
}
这样就实现了动态多态
从多态,引申出抽象类的概念,抽象类没有对象,是派生类的抽象。凡是包含纯虚函数的都是抽象类。
纯虚函数的写法:
virtual void display() const = 0;