经典问题解析三

一. 多态与对象数组的问题

class Parent
{
protected:
	int i;
public:
	virtual  void f()
	{
		cout<<"Parent::f"<<endl;
	}
};

class Child:public Parent
{
protected:
	int j;
public:
	 Child(int i,int j)
	{
		this->i = i;
		this->j= j;
	}
	 void f()
	{
		cout<<"i="<<i<<" "<<"j="<<j<<endl;
	}
};


int main(int argc, char *argv[])
{
    Parent* p=NULL;
    Child* c =NULL;
    Child ca[3] = {Child(1,2),Child(3,4),Child(5,6)};
    
   cout<<"sizeof(Parent)="<<sizeof(Parent)<<endl;
   cout<<"sizeof(Child)="<<sizeof(Child)<<endl<<endl;
   
    
    cout<<hex<<&ca[0]<<endl;
    cout<<hex<<&ca[1]<<endl;
    cout<<hex<<p<<endl;
    cout<<hex<<c<<endl;
    cout<<hex<<(p+1)<<endl;
    cout<<hex<<(c+1)<<endl;
    
    p = ca;
    c = ca;
    
    p->f();
    c->f();
    
    p++;
    c++;
    
   // p->f();  // 运行有问题 
    c->f();
    
 	return 0;
}




   分析: 这是一个多态与数组对象,及指针运算符之间的问题。

       (1)父类中占8个字节,一个int类型,一个virtual函数,所以父类输出8个字节。

       (2) 子类继承了父类,同时又多个一个int类型,所以子类占12个字节。

       (3)p为父类指针,c为子类指针,p++的步长为8,c++的步长为12。


       (4)所以,当p++后,p->show(),出现段错误的原因所在。

二. 多重继承

    C++中对多继承二义性的解决方案

    虚继承:在继承间接共同基类时只保留一份成员。
           为了解决不同途径继承而来的同名数据成员造成的二义性问题,可以将共同基类设置为虚基类,

     。这样从不同的路径继承过来的同名数据成员在内存中只有一个拷贝。

     注意: 虚基类并不是在声明基类时声明的,而是在声明派生类时,指定继承方式时声明的。

    实例:

#include <cstdlib>
#include <iostream>
using namespace std;
#include <string>
class Person
{
protected:
	string name;
	char sex;
	int age;
public:
	Person(string nam,char s,int a):name(nam),sex(s),age(a)
	{
	}
};

class Teacher:virtual public Person
{
protected:
	string title; // 职称
public:
	Teacher(string nam,char s,int a,string t):Person(nam,s,a)
	{
		title = t;
	} 
};

class Student:virtual public Person
{
protected:
	float score; 
public:
	Student(string nam,char s,int a,float sco):Person(nam,s,a),score(sco)
	{
	}
};

class Graduate:public Teacher,public Student
{
private:
	float wage;  // 津贴 
public:
	Graduate(string nam,char s,int a,string t,float sco,float w)
	:Person(nam,s,a),Teacher(nam,s,a,t),Student(nam,s,a,sco),wage(w)
	{}
	void show()
	{
		cout<<"name:"<<name<<endl;
		cout<<"age:"<<age<<endl;
		cout<<"sex"<<sex<<endl;
		cout<<"score"<<score<<endl;
		cout<<"title"<<title<<endl;
		cout<<"wages"<<wage<<endl;
	}	 
};

int main()
{
	Graduate gradl("Wang_li",'f',24,"assistant",89.5,1200);
	gradl.show();
	return 0;
}



三. C++中接口类的实现

     (1) C++中没有接口的概念

     (2) C++中可以使用纯虚函数实现接口

class Interface1
{
public:
	virtual void print()=0;
	virtual int add(int i,int j)=0;	
};

class Interface2
{
public:
	virtual int add(int i,int j)=0;
	virtual int minus(int i,int j)=0;
};

  接口类1 和接口类2 都有一个virtual int add(int i,int j)=0;

class Child:public Interface1,public Interface2
{
public:
	void print()
	{
		cout<<"Child::void print()"<<endl;
	}
	int add(int i,int j)
	{
		return i+j;
	}
	int minus(int i,int j)
	{
		return i-j;
	}
};

   继承类中对两个接口中相同的函数值定义一次就行。

int main()
{
	Child c;
	c.print();
	cout<<c.add(2,3)<<endl;
	cout<<c.minus(5,0)<<endl;
	
	Interface1* i1 =&c;
	Interface2* i2 =&c;
	
	cout<<i1->add(7,8)<<endl;
	cout<<i2->add(4,5)<<endl;
	return 0;
}

    (1) 多重继承接口不会带来二义性和复杂性问题

    (2) 多重继承可以通过精心设计用单例继承和接口来代替

    注意: 接口只是一个功能说明,而不是功能实现。子类需要根据功能说明定义功能实现。












  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值