虚继承、虚函数、模板函数、模板类
知识点:
1. 属性初始化
class Student: public Person{
private:
// char* courseName;
Course course;
public:
Student(char* name,int age,char* courseName):Person(name,age),course(courseName){ // 初始化父类的属性
// this->courseName = courseName;
}
void print(){
cout << name << "," << age << "," << course._name() << endl;
}
};
2. 多继承,(在 java 里面是不允许多继承的, c++ 是可以的, 但是你也不能有二义性(歧义))
class Person {
protected:
char *name;
public:
Person(char *name) {
this->name = name;
}
char *_name() {
return this->name;
}
};
class Child {
int age;
public:
Child(int age) {
this->age = age;
}
int _age() {
return age;
}
};
class Student : public Person, public Child { // 多继承,并没有实现
public:
Student(char *name, int age) : Person(name), Child(age) {
}
};
3. 虚继承(二义性)
作用:解决二义性
,确保继承过来的相同属性或者函数,只存在一份拷贝
class A {
public:
char *name;
};
class B : virtual public A { // 确保继承过来的相同属性或者函数,只存在一份拷贝
};
class C : virtual public A {
};
class D : public B, public C {
};
int main(){
D d;
d.name = "east"; // 如果不用虚继承,会报错:不明确 name 是 B 的 还是 C 的
}
4. c++ 中的多态
c++
中的多态默认情况下不存在
,如果需要使用多态,一定要加上virtual
关键字
c++中多态分两种:
- 动态多态:子父类继承
- 静态多态:方法的重载
class Activity {
public:
// 如果没有 virtual 关键字就没有多态
virtual void onCreate() { // 支持多态,虚函数
cout << "Activity 中的 onCreate" << endl;
}
};
class MainActivity : public Activity {
public:
void onCreate() override {
cout << "MainActivity 中的 onCreate" << endl;
}
};
调用:
Activity *activity1 = new MainActivity();
startActivity(activity1);
5. 纯虚函数(类似于:java 中的 抽象类,接口)
如果全部都是纯虚函数就类似 java 中的 接口
,否则类似 抽象类
virtual void click() = 0; // 必须要加 = 0
class BaseActivity{
public:
void onCreate(){ // 普通函数
initView();
initData();
}
// 子类必须要实现
virtual void initData() = 0; // 虚函数,没有实现的,类似于 java 中的抽象方法,如果子类不实现会报错
virtual void initView() = 0;
};
// 如果不实现父类的纯虚函数,那么 MainActivity 也会变成抽象类,抽象类不允许实例化
class MainActivity:public BaseActivity{
void initData() override{
cout << "initData" << endl;
}
void initView() override {
cout << "initView" << endl;
}
};
class ClickListener{ // 所有的函数都是虚函数,那么就可以认为是接口
public:
virtual void click() = 0; // 必须要加 = 0
};
6. 构造函数和析构函数
- 构造函数:先父类 -> 再子类
- 析构函数: 先子类 -> 再父类
int main(){
// 构造函数:先父类 -> 再子类
// 析构函数: 先子类 -> 再父类
Student* stu = new Student("East",25);
delete (stu);
}
7. 模板函数(java 中的泛型)
7.1.定义:
template <typename T> // 模板函数的定义(不能有分号)
template <typename T> // 模板函数的定义(不能有分号)
T add(T number1,T number2){
return number1+number2;
}
7.2. 当普通函数和模板函数同时存在时,优先会调用普通函数
template <typename T>
T add(int number1, int number2){
cout << "模板函数被调用" << endl;
return number1+number2;
}
int add(int number1,int number2){
cout << "int add 被调用" << endl;
return number1+number2;
}
// so 是很难被反编译,比 java 安全为啥
// samll 语法
int main(){
int sum1 = add(1,2);
double sum2 = add(1.0,2.0);
float sum3 = add(1.0f,2.0f);
cout << sum1 << " , " << sum2 << endl;
}
打印结果:
int add 被调用
int add 被调用
int add 被调用
3 , 3
8.模板类
语法跟模板函数非常相似
template <typename T>
class Callback{
public:
void onError(){
}
void onSucceed(T result){
cout << result << endl;
}
};
// 模板类继承
// 如果子类不是模板类
class HttpCallback : public Callback<int>{
};
// 子类还是模板类
template <typename T>
class HttpCallback : public Callback<T>{
};