- A+
所属分类:C++
构造与析构顺序
- 父类构造函数
- 子类构造函数
- 子类析构函数
- 父类析构函数
同名函数
何为同名成员函数? 即不管参数是否相同、返回值是否相同,只要函数名称相同,就是同名成员函数
#include <iostream> #include <stdlib.h> #include <string> using namespace std; /**父类 * 定义人类: Person * 数据成员: m_strName * 成员函数: attack() */ class Person { public: Person() { cout<<"Person()"<<endl; } Person(const Person& p) { cout<<"Person(const Person& p)"<<endl; } string m_strName; void attack() { cout << "attack" << endl; } }; /**子类 * 定义士兵类: Soldier * 士兵类公有继承人类 * 数据成员: m_strName * 成员函数: attack() */ class Soldier:public Person { public: Soldier() { cout<<"Soldier()"<<endl; } string m_strName; void attack() { cout << "fire!!!" << endl; } }; int main(void) { // 实例士兵对象 Soldier soldier;//实例化子类,会先调用基类构造函数,再调用子类的构造函数,析构时,则相反,先析构子类的,再析构基类的 Person p = soldier;//可以看出子类的对象可以初始化基类的对象,并且这种方式会调用基类的拷贝构造函数 // 向士兵属性赋值"tomato" soldier.m_strName = "tomato"; // 通过士兵对象向人类属性赋值"Jim" soldier.Person::m_strName = "Jim"; // 打印士兵对象的属性值 cout << soldier.m_strName << endl; // 通过士兵对象打印人类属性值 cout << soldier.Person::m_strName << endl;//注意这种使用子类的对象调用基类成员变量的方式 // 调用士兵对象方法 soldier.attack(); // 通过士兵对象调用人类方法 soldier.Person::attack();//注意这种使用子类的对象调用基类的成员函数的方式 return 0; }
输出结果:
Person() Soldier() Person(const Person& p) tomato Jim fire!!! attack
通过上面的例子,分析如下:
- 当子类中含有和基类同名的成员变量时,再用子类的对象调用该同名成员变量时,将只会调用到子类自身定义的成员变量,而不会调用到基类的同名成员变量,这种现象就叫做隐藏,子类把基类的同名成员变量隐藏了,正确调用方式如上面例子中橘色字体部分:soldier.Person::m_strName;
- 当子类中含有和基类同名的成员函数时,再用子类的对象调用该同名成员函数时,将只会调用到子类自身定义的成员函数,而不会调用到基类定义的同名的成员函数,这也是因为子类把基类的同名成员函数隐藏了;正确调用方法应该是如上面例子中橘色字体部分:soldier.Person::attack();
- 只要函数名称相同,即为同名函数,如果函数参数列表不一致,也是同名函数。如果子类和基类定义了这样的函数,子类就会把基类的相应函数隐藏掉。如将基类Person的attack()函数改成带有参数的attack(int x)函数,这个时候用soldier.attack(5)这种方式试图调用基类的attack()仍然会报错,因为Soldier中的attack()函数和父类中的attack(int x)重名,从父类中继承的attack(int x)在子类Soldier中被隐藏,所以子类是调用不到attack(int x)的。