C++一些注意点之继承和派生 (二)

2014-11-24 00:59:33 · 作者: · 浏览: 9
x=a;} //D
};


int main()
{
Der d;
d.Base1::show();
d.Base2::show();
return 0;
}

#include

using namespace std;

class Base1{
int x;
public:
Base1(int a)
{x = a;}
void show(){cout<<"x="< };

class Base2{
int x;
public:
Base2(int b)
{x = b;}
void show(){cout<<"x="< };

class Der:public Base1,public Base2{
private:
int z;
public:
void setAx(int a){Base1:x=a;} //D
void setBx(int a){Base2:x=a;} //D
};


int main()
{
Der d;
d.Base1::show();
d.Base2::show();
return 0;
}

(2)作用域不能连续使用。例如,Der又派生一个类,则不能像这样使用:

[html]
#include

using namespace std;

class Base1{
int x;
public:
Base1(int a)
{x = a;}
void show(){cout<<"x="< };

class Base2{
int x;
public:
Base2(int b)
{x = b;}
void show(){cout<<"x="< };

class Der:public Base1,public Base2{
private:
int z;
public:
void setAx(int a){Base1:x=a;}
void setBx(int a){Base2:x=a;}
};

class Der1:public Der{
private:
public:
};

int main()
{
Der1 d;
d.Der1::Base1::show();//这样的写法是错的
d.Der1::Base2::show();//这样的写法是错的
return 0;
}

#include

using namespace std;

class Base1{
int x;
public:
Base1(int a)
{x = a;}
void show(){cout<<"x="< };

class Base2{
int x;
public:
Base2(int b)
{x = b;}
void show(){cout<<"x="< };

class Der:public Base1,public Base2{
private:
int z;
public:
void setAx(int a){Base1:x=a;}
void setBx(int a){Base2:x=a;}
};

class Der1:public Der{
private:
public:
};

int main()
{
Der1 d;
d.Der1::Base1::show();//这样的写法是错的
d.Der1::Base2::show();//这样的写法是错的
return 0;
}
解决方法:在Der增加成员:

void showA(){cout<<"x="< void showB(){cout<<"x="<


(3)允许派生类的成员和基类的成员重名,但是访问的时候如果不带有作用域,在表示访问派生类中的成员,带有作用域可以访问基类的成员。

(4)赋值兼容规则:派生类的对象可以赋值给基类对象,但是丢生了派生了的信息,基类的对象不能赋值给派生类对象;派生类对象的地址可以赋值给基类的指针变量(派生类对象可以赋值给基类的引用)。


5.虚基类

(1)同一个基类引起的多份copy

这样一个继承关系,A派生B和C,C又派生出D,这样D就有A中的两份copy。如下:


[html]
#include

using namespace std;

class A{
public:
int x;
A(int a){x = a;}
};

class B:public A{
int y;
public:
B(int a=0,int b=0):A(a){y = b;}
void PB(){cout<<"x="< };

class C:public A{
int z;
public:
C(int a=0,int b=0):A(a){z = b;}
void PC(){cout<<"x="< };

class D:public B,public C{
int m;
public:
D(int a,int b,int d,int e,int f):B(a,b),C(d,e)
{m = f;}
void PD()
{
PB();//D 不能换成{cout<<"x="< PC();//E 不能换成{cout<<"x="< cout<<"m="< }
};

int main()
{
D d(100,200,300,400,500);
d.PD();
return 0;
}

#include

using namespace std;

class A{
public:
int x;
A(int a){x = a;}
};

class B:public A{
int y;
public:
B(int a=0,int b=0):A(a){y = b;}
void PB(){cout<<"x="< };

class C:public A{
int z;
public:
C(int a=0,int b=0):A(a){z = b;}
void PC(){cout<<"x="< };

class D:public B,public C{
int m;
public:
D(int a,int b,int d,int e,int f):B(a,b),C(d,e)
{m = f;}
void PD()
{
PB();//D 不能换成{cout<<"x="< PC();//E 不能换成{cout<<"x="< cout<<"m="< }
};

int main()
{
D d(100,200,300,400,500);
d.PD();
return 0;
}
运行结果:


注:D行和E行不能换成相应的语句,这样会引起冲突,必须采用前面作用域的解决方法。


(2)虚继承

在多重派生的过程中,若欲使公共的基类在派生类中只有一份copy,可以将这种基类说明为虚基类。在派生的定义中,在基类的名字前面加上virtual关键字。

在类的对象中都一个虚表指针,指向虚表(每个类含有一个虚表,续表中存放特定类的虚函数地址),虚表里存放了虚函数的地址。虚函数表里顺序存放虚函数地址的,不是链表存储的。在每个带虚函数的类中,编译器秘密设置一指针,称为vpoionter,指向这个对象的虚表,通过基类指针调用的时候静态插入取得这个指针,并在表中查找出函数地址的代码。《宝典p131》


[html]
#include

using namespace std;

class A{
public:
int x;
A(int a=0){x = a;}
};

class B:virtual public A{
int y;
public:
B(int a=0,int b=