快上网专注成都网站设计 成都网站制作 成都网站建设
成都网站建设公司服务热线:028-86922220

网站建设知识

十年网站开发经验 + 多家企业客户 + 靠谱的建站团队

量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决

c++多态-创新互联

多态是c++中很重要的一环。多态可以分为以下几个层面来剖析:

创新互联专注于企业成都全网营销、网站重做改版、营口网站定制设计、自适应品牌网站建设、H5技术成都做商城网站、集团公司官网建设、外贸网站建设、高端网站制作、响应式网页设计等建站业务,价格优惠性价比高,为营口等各大城市提供网站开发制作服务。

  1.对象的类型

  2.多态

  3.虚表

  先说第一点对象的类型,这个非常简单。比如说、

int a;

  那么我就定义了一个int类型的变量a。再来看下面的代码

class Base
{

};

class Derive:public Base
{

};

  这里我写了一个Base类和一个Derive类,并且Derive类是派生于Base类

Base b;
Derive d;

Base* pb=&b;
pb=&d;

  上面的代码实例化了一个Base类类型的对象b,Derive类类型的对象d,Base*类型的指针pb。

pb的静态类型就是Base*类型,我们也可以让pb指向d,Derive*就是pb的动态类型。

  下面来说说第二点,多态。

int Add(int left,int right)
{
    return left+right;
}

double Add(double left,double right)
{
    return left+right;
}

    上面这两个函数构成了函数的重载,传进去int类型的参数就调用上面的,double类型的参数就调用下面的。这也是一种多态,称为静态的多态。还有一种泛型编程也是静态的多态。静态多态就是在编译器编译期间完成的,编译器根据函数的实参的类型(可能进行隐式的类型转换),可推断出到底要调用哪个函数,如果有对应的函数就调用该函数,否则就会出现编译错误。

    那么动态多态(也叫动态绑定)就是指在程序执行期间判断所引用对象的实际类型,根据其实际类型调用相应的方法。

    使用virtual关键字来修饰函数,指明该函数为虚函数,派生类需要重新实现,编译器将实现动态绑定。

  所谓虚函数就是指在类中被声明为virtual的成员,基类希望这种成员在派生类中重定义。除了构造函数外,任意非static成员都可以为虚成员。保留字 virtual 只在类内部的成员函数声明中出现,不能用在类定义体外部出现在函数定义上。

    看一段代码:

class Base
{
public:
    virtual void FunTest()
    {
        cout<<"Base::FunTest()"<FunTest();
    pb=&d;
    pb->FunTest();
    
    return 0;
}

    在这一段代码里面,我定义了两个类一个是Base,另一个是他的派生类Derive。Base类里面有一个虚函数FunTest(),Derive类里面也有一个FunTest()。并且在主函数里面实例化了两个类的对象,并且调用了FunTest函数,下面也定义了Base*类型的指针,先指向b,然后调用了FunTest函数,之后指向d,然后调用FunTest函数。这段代码运行结果会是什么样呢?

c++ 多态

    正如我们所看到的调用派生类里面的函数他有他就调用他自己的,他没有再去基类里面找。

    那么动态绑定实现的条件是什么呢?第一,必须要是虚函数。第二,要通过基类类型的引用或者指针调用。

class CBase
{
public:
	virtual void FunTest1(int _iTest)
	{
		cout << "CBase::FunTest1()" << endl;
	}
	void FunTest2(int _iTest)
	{
		cout << "CBase::FunTest2()" << endl;
	}
	virtual void FunTest3(int _iTest1)
	{
		cout << "CBase::FunTest3()" << endl;
	}
	virtual void FunTest4(int _iTest)
	{
		cout << "CBase::FunTest4()" << endl;
	}

};


class CDerive:public CBase
{
public:
	virtual void FunTest1(int _iTest)
	{
		cout << "CDerive::FunTest1()" << endl;
	}
	virtual void FunTest2(int _iTest)
	{
		cout << "CDerive::FunTest2()" << endl;
	}
	void FunTest3(int _iTest1)
	{
		cout << "CDerive::FunTest3()" << endl;
	}
	virtual void FunTest4(int _iTest1,int _iTest2)
	{
		cout << "CDerive::FunTest4()" << endl;
	}
};

int main()
{
	CBase* pBase = new CDerive;
	pBase->FunTest1(0);
	pBase->FunTest2(0);
	pBase->FunTest3(0);
	pBase->FunTest4(0);
	return 0;
}

    上面是一个例子,CBase类是CDerive类的基类。之后FunTest1()是一个虚函数,FunTest2()不是一个虚函数,FunTest3()也是虚函数,FunTest4()虽然是虚函数但是在子类里面重新实现给了两个参数。所以运行结果是这样的:

c++ 多态

    假如我们想调用CDerive里面的FunTest4(),我们就要用CDerive类的对象了。就像下面这样:

        CDerive d;
	d.FunTest4(0, 0);

    我们这里有一个图片,能看明白继承体系中同名成员函数的关系:
c++ 多态

    这里还需要注意:构造函数是不可以定义为虚函数的,因为构造函数是用来构建我们的对象 的,构造函数没有执行完我们的对象就是不完整的。假如我们要调用构造函数,是需要通过我们的基类对象来调用的,但是我们的对象都没有构造完,所以是不能这样的。

    静态函数和友元函数也同样不可以用virtual来修饰。因为这两种函数都没有this指针。

    这里还有一个东西:

class test
{
	virtual void Test() = 0;
};

    这段代码定义的类叫抽象类。它不能够实例化产生对象,它只是提供一些接口。它里面的那个函数后面跟了一个=0,表示它是纯虚函数,它表示它的派生类要对它这个函数进行重写。

    最后来说虚表和虚指针。

    当我们求sizeof(test)时,我们得出的结果是4。为什么呢?对类求大小的时候不应该是它的成员的大小吗?这里就是有一个虚指针。那这个虚指针指向那里呢?是指向的虚表。虚表里面存的就是虚函数的地址。

    举一个例子:

class test
{
public:
	virtual void FunTest1()
	{}
	virtual void FunTest2()
	{}
	virtual void FunTest3()
	{}
	virtual void FunTest4()
	{}
};

    这个类里面只有四个虚函数,那么sizeof(test)等于多少呢?

c++ 多态

    再来看看t中到底有什么:

c++ 多态

    所以当我们要调用虚函数的时候,编译器是先找到我们的虚表地址,之后找到对应的虚函数。

另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


分享文章:c++多态-创新互联
URL网址:http://6mz.cn/article/ccedcs.html

其他资讯