对象类型转换
向上转型:子类类型转化为父类类型,有意义、安全、可以隐式进行。
向下转型:从父类类型转化为子类类型,不一定有意义、也不一定安全、必须由我们自己进行强制类型转换。
mutable关键字:异变的、可变的,该关键字修饰的变量总能被修改,不受 const 关键字的影响。
虚函数(Virtual Function)
用 virtual 关键字修饰的方法就是虚函数(虚方法)
当用一个父类指针或引用指向某个子类对象时,通过这个指针或引用调用父类中的某个虚函数,如果子类重写(Override)了父类中的这个虚函数,那么调用的将是子类中的那个方法,否则调用的就是父类中的方法。
方法重写(Method Override):子类中显式定义一个和父类中某个虚函数同名(方法名和形参列表均相同)的方法。
如果父类中某个方法为虚函数,那么其所有子类中与该方法同名的方法将自动都是虚函数,可以不用写 virtual 关键字。
多态(Polymorphic)
多种形态。在 面向对象编程(OOP)中,多态就是指同一种调用形式,根据实际情况不同会产生不同的执行结果。
在 C++ 中实现多态的前提:
- 父类指针或父类引用指向某个子类对象。
- 父类中必须有虚函数
实例一:多重继承
#include <iostream>
using namespace std;
class Animal
{
public:
int id;
Animal()
{
cout << "Animal()" << endl;
}
Animal(int id):id(id)
{
cout << "Animal(int)" << endl;
}
~Animal()
{
cout << "~Animal()" << endl;
}
void eat()
{
cout << "I can eat!" << endl;
}
};
class Horse: virtual public Animal // 虚继承,Animal 就是虚基类
{
public:
int h;
Horse()
{
cout << "Horse()" << endl;
}
Horse(int id, int h):h(h)
{
cout << "Horse(int)" << endl;
}
~Horse()
{
cout << "~Horse()" << endl;
}
void run()
{
cout << "I can run fast!" << endl;
}
};
class Donkey: virtual public Animal // 虚继承,Animal 就是虚基类
{
public:
int d;
Donkey()
{
cout << "Donkey()" << endl;
}
Donkey(int id, int d):d(d)
{
cout << "Donkey(int)" << endl;
}
~Donkey()
{
cout << "~Donkey()" << endl;
}
void carry()
{
cout << "I can carry more!" << endl;
}
};
class Mule: public Horse, public Donkey//构造函数调用顺序按从左到右调用
{
public:
Mule()
{
cout << "Mule()" << endl;
}
// 只能由虚基类构造函数负责对从虚基类继承的所有属性进行初始化
Mule(int id, int h, int d): Animal(id), Horse(8, h), Donkey(9, d)
{
cout << "Mule(int, int, int)" << endl;
}
~Mule()
{
cout << "~Mule()" << endl;
}
void show()
{
cout << id << ' ' << h << ' ' << d << endl;
}
};
int main()
{
// Mule* m = new Mule;
//m此时有两个 id, 显然不合理
// m->Horse::id = 3;
// m->Donkey::id = 5;
// m->Animal::id = 9; //不能间接访问
// m->id = 8;
// cout << m->Donkey::id << endl;
// m->Horse::eat();
// m->Donkey::eat();
// m->eat();
// m->h = 5;
// m->d = 6;
// m->run();
// m->carry();
// delete m;
Mule m(1, 2, 3);
m.show();
return 0;
}
实例二:对象类型转换
#include <iostream>
#include <cstring>
using namespace std;
class Person
{
private:
int id = 0;
char name[20] = "";
public:
Person()
{
}
Person(int id, const char* name): id(id)
{
strcpy(this->name, name);
}
void setIdAndName(int id, const char* name)
{
this->id = id;
strcpy(this->name, name);
}
virtual void show() const
{
cout << id << ' ' << name << endl;
}
};
class Chinese: public Person
{
private:
char shengXiao[8] = "";
public:
Chinese()
{
}
Chinese(int id, const char* name, const char* shengXiao): Person(id, name)
{
strcpy(this->shengXiao, shengXiao);
}
void guoNian()
{
cout << "新年快乐!" << endl;
}
void show() const
{
Person::show();
cout << shengXiao << endl;
}
};
class English: public Person
{
private:
char queenName[20] = "";
public:
English()
{
}
English(int id, const char* name, const char* queenName): Person(id, name)
{
strcpy(this->queenName, queenName);
}
void christmas()
{
cout << "Happy Christmas!" << endl;
}
void show() const
{
Person::show();
cout << queenName << endl;
}
};
void showPerson(const Person& p);
int main()
{
Person p1(1003, "lisi"); // 24
English e1(1002, "Tom", "Alisa"); // 44
Chinese c1(1001, "张三", "龙"); // 32
Person* p2 = &c1; // 向上转型,隐式进行
p2->show();
p2 = &e1; // 向上转型,隐式进行
p2->show();
p2 = &p1;
p2->show();
// // 注意该函数的形参和实参类型
// showPerson(p1);
// showPerson(e1);
// showPerson(c1);
// p1 = c1; // 向上转型,隐式进行
// p1.show();
// // e1 = (English)(p1);
// Person& p3 = c1; // 向上转型,隐式进行
// p3.show();
// English* q = (English*)p; // 向下转型,强制转型
// q->show();
// char c[4];
// int* p;
// p = (int*)&c;
// *p = 65;
// // Range based for statement
// // 基于范围的 for 语句
// for(char x : c)
// {
// cout << (int)x << endl;
// }
// double* p = (double*)&c;
// p = (double*)3;
// *p = 3.14;
return 0;
}
void showPerson(const Person& p)
{
p.show();
}
实例三:虚函数
#include <iostream>
using namespace std;
class A
{
public:
int a = 3;
virtual void show()
{
cout << "A::show()" << endl;
}
};
class B: public A
{
public:
int a = 5;
void show()
{
cout << "B::show()" << endl;
}
void show(int i)
{
cout << i << endl;
}
};
class C: public A
{
public:
void show()
{
cout << "C::show()" << endl;
}
};
int main()
{
B b;
C c;
A* p = &b;
cout << p->a << endl;
p->show();
p = &c;
p->show();
return 0;
}