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



