继承的研究(一)
我已经学到的继承是这么回事:
派生类拥有父类的所有变量和方法
因为还没有看C++深入理解对象模型或者之类的这种书,我也不想直接查资料,因此准备自己写几行代码进行实验
现在我有这几个疑问
- 当父类与子类变量同名的时候,怎么进行区分
- 当父类与子类函数同名的时候,怎么进行处理
- 当父类与子类函数和变量同名的时候,怎么进行处理
父类与子类变量同名
父类与子类变量同名也分成这几种情况,我将一一进行探讨
- 父类public变量与子类public变量同名
- 父类private变量与子类private变量同名
- 父类public变量与子类private变量同名
- 父类private变量与子类public变量同名
使用以下代码进行探讨
#include <iostream>
using namespace std;
class Parent
{
public:
Parent():pub(0), pri(0){};
public:
int pub;
private:
int pri;
};
class Child: Parent
{
public:
Child():pub(1), pri(1){};
public:
void printSelf()
{
cout << pub << " " << pri << endl;
}
public:
int pub;
private:
int pri;
};
int main()
{
Child c;
c.printSelf();
return 0;
}
打印结果如下:
1 1
即:若子类变量与父类变量在public区域同名,则子类内会优先使用自己的变量
我老实思考了一下,大概应该是这么回事:
当类使用一个元素的时候,首先它会在自己的定义里面找名字,找到名字以后再比较类型,若名字和类型都符合就算找到了,如果没有找到再到它的祖先那里去找
这样子我又有一个问题了:
如果有两个基类,基类有一样的public变量,那么,又将怎么样呢
改写代码如下:
class Parent1
{
public:
Parent1() :pub(1), pri(1){};
public:
int pub;
private:
int pri;
};
class Parent2
{
public:
Parent2() :pub(2), pri(2){};
public:
int pub;
private:
int pri;
};
class Child
: Parent1, Parent2
{
public:
Child()
{
cout << pub << " " << pri << endl;
}
};
int main()
{
Child child;
return 0;
}
这么写就报错了,编译器说pub和pri的来源是ambiguous的
虽然已经猜到了问题3和问题4的结果,但是我还是打算试一试
class Parent1
{
public:
Parent1() :pub(1), pri(1){};
public:
int pub;
private:
int pri;
};
class Child: Parent1
{
public:
Child(): pri(2), pub(2)
{
cout << pub << " " << pri << endl;
}
public:
int pri;
private:
int pub;
};
int main()
{
Child child;
return 0;
}
输出结果果然是2 2
但是,在进行Child进行构造的时候,我发现了一个有趣的现象:
先构造Child的pub即它的pricate变量、后构造它的pri即public变量,编译时会产生警告:
main.cpp: In constructor ‘Child::Child()’:
main.cpp:32:6: warning: ‘Child::pub’ will be initialized after [-Wreorder]
32 | int pub;
| ^~~
main.cpp:30:6: warning: ‘int Child::pri’ [-Wreorder]
30 | int pri;
| ^~~
main.cpp:25:2: warning: when initialized here [-Wreorder]
25 | Child(): pub(2), pri(2)
| ^~~~~
为了再研究变量的初始化顺序,我写下了如下代码:
int times = 0;
class Child
{
public:
Child()
{
cout << v1 << " " << v2 << endl;
}
public:
int v1 = times ++;
private:
int v2 = times ++;
};
int main()
{
Child child;
return 0;
}
多次实验,最后的输出结果均为:
0 1
是否一定就是public先初始化然后再初始化private呢?
如果是多个变量呢?初始化顺序是否与代码行的前后顺序有关?
为了减少自己的疑虑,我改写了自己的代码
int times = 0;
class Child
{
public:
Child()
{
cout << v1 << " "
<< v2 << " "
<< v3 << " "
<< v4 << " "
<< endl;
}
private:
int v1 = times ++;
int v3 =times ++;
public:
int v2 = times ++;
int v4 = times ++;
};
int main()
{
Child child;
return 0;
}
多次实验的结果均为
0 2 1 3
即说明:
- 初始化变量的顺序与变量在private里还是在public里无关
- 初始化变量的顺序只与代码顺序有关
总结
因为时间的关系,我并没有太多功夫把函数也做了,但是通过对变量的探究,我大概能猜到其规律,留给下一次来做实验
今天学到的东西有:
- C++类的变量初始化顺序与其类型无关,只与代码顺序有关
- C++在一个类里面找一个变量,首先会在这个类的定义里面找同名的变量,找到以后比较类型,如果没有找到,就会去父类找。这个规则是递归的
- 如果两个父类都有同一个变量名,则,若在子类中要使用父类的变量,必须声明namespace,否则,编译都过不去