https://blog.csdn.net/alpha_love/article/details/75222175
#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;
#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
通过上面的例子,对于基类和子类之间的特性可以做如下的总结:
(1)当子类中含有和基类同名的成员变量时,再用子类的对象调用该同名成员变量时,将只会调用到子类自身定义的成员变量,而不会调用到基类的同名成员变量,这种现象就叫做隐藏,子类把基类的同名成员变量隐藏了,正确调用方式如上面例子中橘色字体部分:soldier.Person::m_strName;
(2)当子类中含有和基类同名的成员函数时,再用子类的对象调用该同名成员函数时,将只会调用到子类自身定义的成员函数,而不会调用到基类定义的同名的成员函数,这也是因为子类把基类的同名成员函数隐藏了;正确调用方法应该是如上面例子中橘色字体部分:soldier.Person::attack();
这里要强调的是何为同名成员函数,即不管参数是否相同、返回值是否相同,只要函数名称相同,就是同名成员函数,如果子类和基类定义了这样的函数,子类就会把基类的相应函数隐藏掉。在上面的例子中加入我们在基类Person的attack()函数里面添加参数int x,这个时候用soldier.attack(5)这种方式试图调用基类的attack()仍然会报错,是调用不到的。