静态多态
:程序在编译阶段
就可以确定调用哪个函数。这种情况叫做静态多态。比如重载,编译器根据传递给函数的参数和函数名决定具体要使用哪一个函数。
动态多态
:在运行期间
才可以确定最终调用的函数。需要通过虚函数+封装+继承实现。
继承
中。多个子类继承同一基类,若在某种行为上不同的派生类有着自己的实现方式。这种情况我们就会用到多态
。父类中此方法并没有设置为虚函数
。那么通过指向子类的指针或引用调用此方法的时候,调用的是父类的方法
。指针或引用
调用虚函数时,才会在运行时解析该调用。内联函数
构造函数
静态成员函数
:static成员函数是属于类的。不属于任何对象。友元函数
:不支持继承,没有实现为虚函数的必要赋值运算符
:赋值运算符要求形参类型与本身类型相同,基类中赋值操作符形参为基类类型,即使声明成虚函数,也不能作为子类的赋值操作符内联函数为什么不能被定义成虚函数?
内联函数是为了在代码中直接展开,减少函数调用花费的代价。
inline 函数是在编译
时确定的,而 virtual 属性是在运行
时确定的,因此这个两个属性是不可能同时定义的。
即使虚函数被声明为内联函数
,编译器遇到这种情况根本不会把这样的函数内联展开
,而是当作普通函数
来处理。
构造函数为什么不能被定义成虚函数?
如下:
1:继承
情况下,构造函数的执行顺序时:A() B(),先执行父类
的构造函数,在执行子类
的构造函数
2:如果A的构造函数是虚函数,B类也定义了构造函数(即也为虚函数),则只会执行子类的构造函数
。即只会执行B类的构造函数,不会再执行A类的构造函数,这样的话父类A就不能构造了
。
这样的话1和2就发生了矛盾。并且 virtual 函数是在不同类型的对象
产生不同的动作,现在对象还没产生,是不存在通过virtual实现不同动作的想法的。
class A
{
A() {}
};
class B : public A
{
B() : A() {}
};
int main()
{
B b;
B * pb = &b;
}
对象名访问虚函数
的时候,此时采用的是静态联编
。调用哪个类的函数取决于定义对象名的类型
。对象类型是基类时,就调用基类的函数;对象类型是子类时,就调用子类的函数。指针访问虚函数
的时候,编译器根据指针所指对象的类型
来决定要调用哪个函数(动态联编
),而与指针本身的类型无关指针访问虚函数类似
。不同之处在于,引用一经声明后,引用变量本身无论如何改变,其调用的函数就不会在改变
,始终指向其开始定义时的函数。引用在一定程度上提高了代码的安全性,可以将引用理解为一种“受限制的指针”。如 B:A,A是基类,B是子类
构造
子类对象时,先运行基类构造函数
初始化基类部分,再执行子类的构造函数
初始化子类部分。在执行基类构造函数时,派生部分还是未初始化的。实际上,此时对象还不是一个派生类对象。即先 A 后 B
撤销
子类对象时,首先撤销子类
部分,然后按照与构造顺序的逆序撤销它的基类
部分。即先B 后 A
下面看一个例子:
#include
using namespace std;
class Father
{
public:
Father()
{
cout << "Father Constructor" << endl;
}
void calcMethod()
{
cout << "Father calcMethod()" << endl;
}
virtual void virtualMethod()
{
cout << "Father virtualMethod()" << endl;
}
virtual void virtualCommon()
{
cout << "Father virtualCommon()" << endl;
}
~Father()
{
cout << "Father disConstruct" << endl;
}
};
class Son:public Father
{
public:
Son()
{
cout << "Son Constructor" << endl;
}
void calcMethod()
{
cout << "Son calcMethod()