一、封装
封装就是把客观的事物封装成抽象的类,并且类可以对自己的数据或方法只让只让信任的类或者对象操作,对不可信的对象进行信息隐藏。在一个对象内部,某些方法和数据可以是私有的,不可以被外界访问,通过这种方式,对对象内部的不同数据提供了不同级别的保护,防止与程序无关的意外使用或改变了对象的私有部分
二、继承
继承是指让某个类型的对象获得另外一个类型的的对象的的属性的方法。
继承可以实现:使用现有类的功能,并且在无需编写原来类的情况下对原来类的功能进行扩展。通过继承创建的新类称为子类或者派生类,被继承的类称为父类或者基类。
三、多态
c++多态分为静态多态和动态多态
静态多态就是重载,在编译期确定函数地址
动态多态通过继承重写基类的虚函数实现多态,在运行期确定函数的地址
多态的实现原理:
1、用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。
2 、存在虚函数的类都有一个一维的虚函数表叫做虚表。当类中声明虚函数时,编译器会在类中生成一个虚函数表
3、类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。
4、虚函数表是一个存储类成员函数指针的数据结构。
5、virtual成员函数会被编译器放入虚函数表中。
6、当存在虚函数时,每个对象中都有一个指向虚函数的指针(C++编译器给父类对象,子类对象提前布局vptr指针),当进行test(parent *base)函数的时候,C++编译器不需要区分子类或者父类对象,只需要再base指针中,找到vptr指针即可)
虚表
class Base
{
public :
virtual void func1()
{}
virtual void func2()
{}
private :
int a ;
};
void Test1 ()
{
Base b1;
}
单继承对象模型
class Base
{
public :
virtual void func1()
{
cout<<"Base::func1" <<endl;
}
virtual void func2()
{
cout<<"Base::func2" <<endl;
}
private :
int a ;
};
class Derive :public Base
{
public :
virtual void func1()
{
cout<<"Derive::func1" <<endl;
}
virtual void func3()
{
cout<<"Derive::func3" <<endl;
}
virtual void func4()
{
cout<<"Derive::func4" <<endl;
}
private :
int b ;
};
typedef void (* FUNC) ();
void PrintVTable (int* VTable)
{
cout<<" 虚表地址>"<< VTable<<endl ;
for (int i = 0; VTable[i ] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,->", i , VTable[i ]);
FUNC f = (FUNC) VTable[i ];
f();
}
cout<<endl ;
}
void Test1 ()
{
Base b1 ;
Derive d1 ;
int* VTable1 = (int*)(*( int*)&b1 );
int* VTable2 = (int*)(*( int*)&d1 );
PrintVTable(VTable1 );
PrintVTable(VTable2 );
}
派生类重写了基类的fun1() 覆盖了虚表上面相应的函数
多继承对象模型
class Base1
{
public :
virtual void func1()
{
cout<<"Base1::func1" <<endl;
}
virtual void func2()
{
cout<<"Base1::func2" <<endl;
}
private :
int b1 ;
};
class Base2
{
public :
virtual void func1()
{
cout<<"Base2::func1" <<endl;
}
virtual void func2()
{
cout<<"Base2::func2" <<endl;
}
private :
int b2 ;
};
class Derive : public Base1, public Base2
{
public :
virtual void func1()
{
cout<<"Derive::func1" <<endl;
}
virtual void func3()
{
cout<<"Derive::func3" <<endl;
}
private :
int d1 ;
};
typedef void (* FUNC) ();
void PrintVTable (int* VTable)
{
cout<<" 虚表地址>"<< VTable<<endl ;
for (int i = 0; VTable[i ] != 0; ++i)
{
printf(" 第%d个虚函数地址 :0X%x,->", i , VTable[i ]);
FUNC f = (FUNC) VTable[i ];
f();
}
cout<<endl ;
}
void Test1 ()
{
Derive d1 ;
int* VTable = (int*)(*( int*)&d1 );
PrintVTable(VTable );
// Base2虚函数表在对象Base1后面
VTable = (int *)(*((int*)&d1 + sizeof (Base1)/4));
PrintVTable(VTable );
}
后面转自https://blog.csdn.net/qq_40840459/article/details/80195158?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522165062787516782094856136%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=165062787516782094856136&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allbaidu_landing_v2~default-1-80195158.142v9control,157v4control&utm_term=c%2B%2B%E5%A4%9A%E6%80%81%E7%9A%84%E5%AE%9E%E7%8E%B0&spm=1018.2226.3001.4187