NDK-024: C++05: 虚继承、虚函数、函数模板
24.虚继承、虚函数、函数模板
1.属性初始化
#include<iostream>
using namespace std;
class Person{
protected:
char* name;
int age;
public:
Person(char*name, int age){
this->name = name;
this->age = age;
}
}
class Student: public Person{
private:
char* courseName; //string
public:
// 初始化父类的属性
//Student(char*name, int age, char* courseName) :Person(name, age) {
Student(char*name, int age, char* courseName) :Person(name, age),courseName(courseName) {
}
void print() {
cout << name<< ","<<age<< "," <<courseName<< endl;
}
}
void main() {
Student *stu = new Student("Darren",22,"math");
stu->print();
delete stu;
}
对象嵌套时,相当于调用了Course对象的构造函数。
private: Cource course;
Student(char*name, int age, string courseName) :Person(name, age),course(courseName) {
}
cout<< name << ","<< course._name().c_str() <<endl;
String 是对char[]的封装。
string 也是对char*的封装。
2. 支持多继承
Java单继承,C++可以多继承,但是也不能有二义性(不能有歧义)。
继承过程中的二义性,---> 虚继承 virtual
class Student() : Person,Child {
public:
// 多继承,并没有多实现。
Student(char* name, int age) :Person(name),Child(age){
}
}
class A {
public: char* name;
};
public B :virtual public A { // 确保继承过来的相同属性或函数,只存在一分拷贝。消除二义性。
}
public C :virtual public A {
}
public D : public B,public C {
}
3.C++中的多态
C++默认是没有多态的,默认情况下不存在。
在子类中,方法要添加virtual 关键字,虚函数,来支持多态。
Java 父类指向子类的引用,重写,是里氏替换原则的体现。
程序在编译期时,并不知道运行的姿态(要运行那个函数)。
只有在真正运行的过程中,才会去找需要运行的方法。
Java的多态解释,会调用MainActivity的方法。
class Activity{
public:
virtual void onCreate() {
cout << "Activity-- onCreate" << endl;
}
}
class MainActivity : public Activity {
public:
void onCreate() { // 重写
cout << "MainActivity -- onCreate" << endl;
}
}
void startActivity(Activity* activity){
activity->onCreate();
}
void main() {
Activity *activtiy = new MainActivity(); // 传父类的指针
startActivity(activity); // 打印:Activity-- onCreate
}
静态多态和动态多态
编译过程中的区别,编译过程确定性的区别。
动态多态: 子父类继承,虚函数。 类编译时不知道运行哪个,会根据virtual状态。
运行过程中,才知道运行哪个函数。
静态多态: 本类,函数的重载。 编译期间就知道要找那个函数。
4.抽象类和接口 纯虚函数。 跟java的抽象类一个概念。
class BaseActivity{
public:
void startActivity(){
initData();
initView();
} // 普通函数
// 子类需要实现
virtual void initData() =0;
virtual void initView() =0; // 纯虚函数,没有实现,类似java的抽象方法。子类必须实现。
}
class MainAcivity: public BaseActivity
{ // 抽象类不允许实例化,必须要实现。
public:
void initData(){ // 必须实现父类纯虚函数
cout << "initData"<<endl;
}
void initView(){
cout << "initView"<<endl;
}
}
void main() {
BaseAcivity *ma = new MainAcivity();
ma->initView();
}
接口: 所有的函数都是虚函数,就认为是接口。
class ClickListener {
public:
virtual void click() = 0;
};
class ImageClickListener :public ClickListener {
public:
void click() {
cout << "图片点击"<< endl;
}
};
// 纯虚函数回调
void click(ClickListener *listener) {
listener->click();
}
// 另外的一个类, 函数的指针作为参数传递。可作为不断的回调。
// 返回值(函数名)(参数)
void click(void(*c)()) {
c(); // 输出压缩进度
}
void click() {
cout << "click点击" << endl;
}
void main () {
ClickListener *listener = new ImageClickListener();
listener->click();
// click(listener);
click(click);
}
函数指针: 回调可以用 指针函数作为回调,
现在可以用纯虚函数类 来进行回调(接口)。
构造函数和析构函数。 子父类之间的调用顺序。
构造函数:先父类调用,再子类调用;
析构函数:先子类调用,再父类调用。
5. 模板函数 template :相当于java的泛型。
Parcel.cpp readAligned就用到了。
template<class T> 根据sizeof(T) 往后挪动指定字节。
// 加法方法,要针对double,int,float定义三个方法。
// 借助模板函数,减少代码. 模板函数的定义。
template<typename T>
T add(T num1, T num2) {
return num1 + num2;
}