嵌入式C++(四)
文章目录
一、继承
1.1 继承中的类型兼容性原则
概念:类型兼容性原则是指在需要基类对象的地方,我们都可以直接使用公有派生类对象,通过公有继承,我
们可以得到基类中除了构造函数,析构函数外的所有成员,这样,凡是基类可以解决的问题,派生类都可以解
决。
(1)子类对象可以当成父类对象使用,子类对象是一种特殊的父类。
(2)父类指针可以直接指向子类对象
(3)父类引用可以直接引用派生类对象
#include <iostream>
using namespace std;
class Parent
{
protected:
int m_a;
int m_b;
public:
Parent()
{
cout<<"Parent的无参构造函数"<<endl;
}
Parent(const Parent &obj)
{
cout<<"Parent的拷贝构造函数"<<endl;
m_a = obj.m_a;
m_b = obj.m_b;
}
void SetAB(int a,int b)
{
m_a = a;
m_b = b;
}
void print()
{
cout<<"m_a = "<<this->m_a<<endl;
cout<<"m_b = "<<this->m_b<<endl;
}
};
class Child:public Parent
{
private:
int m_c;
public:
void SetC(int c)
{
this->m_c = c;
}
void printC()
{
cout<<"c = "<<m_c<<endl;
}
};
int main(int argc, char const *argv[])
{
/*
Parent p1;
p1.SetAB(1,2);
p1.print();
*/
Child c;
c.SetAB(10,20);
c.SetC(30);
c.print();
c.printC();
// Parent &p = c;
// p.printC();//不能使用
//Child *pc = &c;
//Parent *p = &c;
//p->SetAB(1,2);
//p->SetC(20);
return 0;
}
1.2 多继承
(1) 概念
派生类中如果只有一个基类,称为单继承,除此之外,c++中还支持多继承,每一个派生类可以继承多个基
类。
(2)多继承的语法
用逗号将继承的基类隔开。
#include <iostream>
using namespace std;
class AirPlane
{
protected:
int high;
public:
AirPlane()
{
cout<<"飞机的构造函数"<<endl;
high = 100;
}
void show()
{
cout<<"飞机的高度"<<high<<endl;
}
};
class Ship
{
protected:
int speed = 40;
public:
Ship()
{
cout<<"轮船的构造函数"<<endl;
}
void show()
{
cout<<"航行的速度:"<<speed<<endl;
}
};
class WaterPlane:public Ship,public AirPlane
{
public:
WaterPlane()
{
cout<<"水上飞机的构造函数"<<endl;
}
};
int main(int argc, char const *argv[])
{
WaterPlane w;
cout<<sizeof(w)<<endl;
w.AirPlane::show();
w.Ship::show();
return 0;
}
(2)多继承的构造和析构
#include <iostream>
using namespace std;
class AirPlane
{
protected:
int high;
public:
AirPlane(int h):high(h)
{
cout<<"飞机的构造函数"<<endl;
}
~AirPlane()
{
cout<<"飞机的析构函数"<<endl;
}
};
class Ship
{
protected:
int speed;
public:
Ship(int s):speed(s)
{
cout<<"轮船的构造函数"<<endl;
}
~Ship()
{
cout<<"轮船的析构函数"<<endl;
}
};
class WaterPlane:public Ship,public AirPlane
{
public:
WaterPlane(int h,int s):AirPlane(h),Ship(s)
{
cout<<"水上飞机的构造函数"<<endl;
}
~WaterPlane()
{
cout<<"水上飞机的析构函数"<<endl;
}
};
int main(int argc, char const *argv[])
{
WaterPlane w(100,40);
return 0;
}
(3)多继承的二义性
#include <iostream>
using namespace std;
class TestA
{
public:
int a[7];
};
class TestB:public TestA
{
public:
int b;
};
class TestC:public TestA
{
public:
int c;
};
class TestD:public TestB,public TestC
{
public:
int d;
};
int main(int argc, char const *argv[])
{
TestD td;
cout<<sizeof(td)<<endl;
//td.a;//会报错,不知道是哪个a
return 0;
}
(4) 虚继承
虚继承的目的是为了让某个类作出声明,承若愿意共享它的基类,这个被共享的基类称为虚基类,在这种情况
下,无论虚基类在继承体系中出现多少次,在派生类中只会为其开辟一次内存空间
#include <iostream>
using namespace std;
class TestA
{
public:
int a;
};
class TestB:virtual public TestA
{
public:
int b;
};
class TestC:virtual public TestA
{
public:
int c;
};
class TestD:public TestB,public TestC
{
public:
int d;
};
int main(int argc, char const *argv[])
{
TestB tb;
cout<<sizeof(tb)<<endl;
cout<<&tb<<endl;
cout<<&tb.a<<endl;
cout<<&tb.b<<endl;
TestD td;
cout<<sizeof(td)<<endl;
cout<<&td<<endl;
cout<<&td.a<<endl;
cout<<&td.b<<endl;
cout<<&td.c<<endl;
cout<<&td.d<<endl;
return 0;
}
二、多态
2.1 问题
#include <iostream>
using namespace std;
class Parent
{
public:
void show()
{
cout<<"this is Parent"<<endl;
}
};
class Child:public Parent
{
public:
void show()
{
cout<<"this is child"<<endl;
}
};
int main(int argc, char const *argv[])
{
Parent *p1 = new Child; //静态联编,编译器会p1的类型,调用parent里面的show函数
p1->show();
return 0;
}
2.2 多态的概念和使用
多态:多种形态,使用多态,当基类指针指向基类对象的时候,期待其按照基类的方法做事,当基类指针指向派生类对象的时候,就按照派生类的方法做事,实现同一个接口,多种方法,它有多种形态,这种现象称为多态。
多态的条件:
1.要有继承
2.要有虚函数重写(发生在不同的作用域,函数原型相同)
3.基类指针指向派生类对象
#include <iostream>
using namespace std;
class Parent
{
public:
virtual void show()
{
cout<<"this is Parent"<<endl;
}
};
class Child:public Parent //1.要有继承
{
public:
void show() //2.要有虚函数重写
{
cout<<"this is child"<<endl;
}
};
int main(int argc, char const *argv[])
{
Parent *p1 = new Child; //3.基类指针指向不同的对象
p1->show();
delete p1;
p1 = new Parent;
p1->show();
delete p1;
return 0;
}
2.3 多态的原理
#include <iostream>
using namespace std;
class Parent
{
public:
int a;
virtual void show()
{
cout<<"this is Parent"<<endl;
}
};
class Child:public Parent //1.要有继承
{
public:
void show() //2.要有虚函数重写
{
cout<<"this is child"<<endl;
}
};
int main(int argc, char const *argv[])
{
Parent p;
Child c;
cout<<sizeof(p)<<endl;
cout<<sizeof(c)<<endl;
cout<<"Parent的起始地址:"<<&p<<endl;
cout<<"成员变量a的起始地址:"<<&p.a<<endl;
return 0;
}
2.4 虚析构函数
根据析构的规则,只能从当前基类开始往上析构,而并不能调用到派生类中的析构函数,通过将基类的析构函数设置成虚函数,调用delete后,使其可以按照正确的顺序析构动态创建的对象。
#include <iostream>
using namespace std;
class Parent
{
public:
int a;
virtual void show()
{
cout<<"this is Parent"<<endl;
}
Parent()
{
cout<<"Parent的构造函数"<<endl;
}
virtual ~Parent()
{
cout<<"Parent的析构函数"<<endl;
}
};
class Child:public Parent //1.要有继承
{
public:
void show() //2.要有虚函数重写
{
cout<<"this is child"<<endl;
}
Child()
{
cout<<"Child的构造函数"<<endl;
}
~Child()
{
cout<<"child的析构函数"<<endl;
}
};
int main(int argc, char const *argv[])
{
Parent *p = new Child;
delete p;
return 0;
}
2.5 动态类型识别
dynamic_cast
1.dynamic_cast是c++新型关键词
2.dynamic_cast用于基类和派生类之间的转换
3.dynamic_cast要求使用的目标类型是多态的。
即要求所在类中至少有一个虚函数。
用于指针转换时,转换失败会返回NULL指针。
用于引用转换时,转换失败会引发bad_cast异常。
优势:
1. 不需要显示的声明和定义虚函数
2. 不用为每个类分配类型ID
缺点:
1.只能用于有虚函数的类
#include <iostream>
using namespace std;
class Parent
{
private:
int m_a;
public:
enum{ID = 0};
virtual int GetId()
{
return ID;
}
};
class Child:public Parent
{
public:
int array[102400];
enum{ID = 1};
virtual int GetId()
{
return ID;
}
};
void func(Parent *p)
{
//Child *c = (Child *)p;
if(p->GetId() == Child::ID)
{
Child *c = (Child *)p;
c->array[102400 -1] = 100;
cout<<"转换成功"<<endl;
}
else
{
cout<<"转换失败"<<endl;
}
}
int main(int argc, char const *argv[])
{
Parent *p = new Child;
//Parent *p = new Parent;
func(p);
return 0;
}
2.6 dynamic_cast
#include <iostream>
using namespace std;
class Parent
{
private:
int m_a;
public:
virtual void show(){}
};
class Child:public Parent
{
public:
int array[102400];
public:
virtual void show(){}
};
void func(Parent *p)
{
Child *c = dynamic_cast<Child *>(p); //如果p指向的是基类对象,则转换失败,转换失败返回NULL
if(NULL == c)
{
cout<<"转换失败"<<endl;
}
else
{
c->array[102400 -1] = 100;
cout<<"转换成功"<<endl;
}
}
int main(int argc, char const *argv[])
{
Parent *p = new Child;
//Parent *p = new Parent;
func(p);
return 0;
}
2.7 typeid
typeid可以用于获取一个表达式的类型信息
typeid的操作对象既可以是表达式,也可以是数据类型
typeid(dataType);
或者:
typeid(expression);
#include <iostream>
#include <typeinfo>
using namespace std;
class Parent
{
private:
int m_a;
public:
virtual void show(){}
};
class Child:public Parent
{
public:
int array[102400];
public:
virtual void show(){}
};
void func(Parent *p)
{
if(typeid(*p) == typeid(Child))
{
Child *c = (Child *)p;
c->array[102400 -1] = 100;
cout<<"转换成功"<<endl;
}
else if(typeid(*p) == typeid(Parent))
{
cout<<"转换失败"<<endl;
}
}
int main(int argc, char const *argv[])
{
int a;
char ch;
Parent p1;
Child c1;
const type_info &pa = typeid(a);
const type_info &pch = typeid(ch);
const type_info &pp1 = typeid(p1);
const type_info &pc1 = typeid(c1);
cout<<pa.name()<<endl;
cout<<pch.name()<<endl;
cout<<pp1.name()<<endl;
cout<<pc1.name()<<endl;
Parent *p = new Child;
//Parent *p = new Parent;
func(p);
return 0;
}
2.8 纯虚函数
virtual 返回值类型 函数名 (函数形参)= 0;
#include <iostream>
using namespace std;
class Parent //含有纯虚函数的类称为抽象类,抽象类不能实例化对象
{
public:
virtual void show() = 0; //纯虚函数,没有函数体
};
class Child:public Parent
{
public:
virtual void show()
{
cout<<"this is child"<<endl;
}
};
int main(int argc, char const *argv[])
{
Parent *p = new Child;
p->show();
return 0;
}