目录
类型兼容规则
先上代码
#include<iostream>
using namespace std;
class Base1
{
public:
void display() const; //Base1成员函数
};
void Base1::display() const //Base1成员函数的实现
{
cout<<"Base1::display()"<<endl;
}
class Base2:public Base1
{
public:
void display() const;
};
void Base2::display() const
{
cout<<"Base2::display()"<<endl;
}
class Base3:public Base2
{
public:
void display() const;
};
void Base3::display() const
{
cout<<"Base3::display()"<<endl;
}
void main()
{
Base1 base1;
Base2 base2;
Base3 base3;
Base1 *ptr1;
Base2 *ptr2;
ptr1=&base1;
ptr1->display();
ptr1=&base2;
ptr1->display();
ptr1=&base2;
ptr1->display();
ptr2=&base3;
ptr2->display();
base2.display();
base3.display();
base3.Base1::display();
base3.Base2::display();
system("pause");
}
根据我们所说的类型兼容规则,是可以将派生类的地址赋值给基类的指针的(这也是为后面的多态规则奠定了基础),但是呢,通过这个指针只能访问到基类中的成员,所以就出现本程序中虽然把指针赋值了对象base2和base3的地址,但是到最后还是调用了基类里的同名成员函数,并且还可以用派生类的对象来对基类的引用或者对象进行初始化。
我们就这个程序说一下,你看我又设了一个ptr2的指针,然后指向了base2和base3的地址,由上面所说,ptr2=&base3;ptr2->display();这时候base2相当于变成了基类,所以此时调用的的是base2的display()。
要想调用对应的派生类里的成员函数,就要通过作用域分辨符,base3.Base1::display();base3.Base2::display();这两行代码就很好的解决了派生类里面成员函数被隐藏的问题。
多继承构造函数、析构函数、派生类成员隐藏问题
上代码
#include<iostream>
using namespace std;
class Base1
{
public:
Base1(int i):i(i){cout<<"调用了Base1的构造函数"<<endl;}
void Base1::display() const ;
~Base1() {cout<<"调用了Base1的析构函数"<<endl;}
private:
int i;
};
void Base1::display() const //Base1成员函数的实现
{
cout<<"Base1::display()"<<endl;
}
class Base2
{
public:
Base2(){cout<<"调用了Base2的构造函数"<<endl;}
void display() const;
~Base2() {cout<<"调用了Base2的析构函数"<<endl;}
};
void Base2::display() const
{
cout<<"Base2::display()"<<endl;
}
class Base3:public Base2,public Base1 //多重继承,继承过程中是不会继承基类里面的构造函数和析构函数的
{
public:
Base3(int a,int b,int c):Base1(a),Base2(),menber2(),menber1(b){ j=c;}
void display() const;
~Base3() {}
private:
int j;
Base2 menber2; //这里也会调用构造函数,并且调用构造函数的顺序跟此处定义的顺序一样,那调用析构函数就是相反的
Base1 menber1; //看到这里的小伙伴不妨试试改变下此处的顺序来验证下
};
void Base3::display() const
{
cout<<"Base3::display()"<<endl;
}
void main()
{
{
Base3 base3(1,2,3);
//Base3 *ptr = &base3; //这是一种给指针赋值的方法
Base3 *ptr; //这是另一种指针赋值的方法
ptr=&base3;
base3.display();
base3.Base1::display();//通过对象和作用域来访问基类的成员函数
base3.Base2::display();
ptr->Base1::display();//这里也是一样的,只是换成了通过指针和作用域分辨符来访问基类的成员函数
ptr->Base2::display();
}
system("pause");
}
多继承派生类定义构造函数的时候要把继承的基类中所有的参数写在参数列表中,在通过:分隔,对继承过来的基类进行初始化,如果在多继承派生类中定义了基类的对象,那么还需要对对象进行初始化(注:基类中有参数的构造函数必须在多继承派生类的构造函数中写出初始化的式子,无参数的可写可不写,可以按照我的代码把构造函数中的Base2()和menber2()去掉)。
调用多继承派生类的时候,你继承基类的顺序就是程序运行时调用基类构造函数的顺序,我的程序中又调用了两次基类的构造函数,这是因为我在多继承派生类的私有成员中定义了两个基类对象,这时的程序调用基类构造函数的顺序也就是你自己定义的基类的顺序。
这里通过继承类对象指针和继承类对象通过作用域分边符来分别调用了两个基类里的同名成员函数,这同样解决了成员被隐藏的问题。