1 隐藏(重定义)
隐藏是指:在基类和派生类中有同名的成员变量或成员函数,那么派生类的成员变量、成员函数就将基类的隐藏(重定义)了。
如何调用隐藏的成员函数(或使用隐藏的成员变量)?
指定作用域
2 派生类的六个默认成员函数
在默认情况下,派生类的默认成员函数由基类的成员函数合成(具体实现见下面的代码)
(1)构造函数
子类的构造函数,继承了父类的构造函数,需要先调用父类的构造函数,再构造自己的成员。
对于子类中继承而来的父类的成员,一般可以采用匿名对象的方式进行初始化
(2)拷贝构造
对子类的拷贝构造,先将参数t中切片给子类中从父类继承而来的成员,再对子类中自己的成员进行拷贝构造。
(3)赋值运算符重载
赋值运算符的函数均为operator=,所以明显子类和父类的赋值运算符重载函数的函数名一样,构成隐藏(重定义),在子类中调用父类的赋值运算符重载函数时需要指定作用域。
(4)析构函数
一般析构函数不显示的调用。
虽然子类和父类的函数名不同,但在编译器中会对析构函数进行处理,全部变为函数名为distructor的函数,所以析构函数也构成隐藏(重定义),如果想要调用父类的析构函数,必须指定作用域。
析构函数是先析构子类自己的成员,再调用父类的析构函数。
//派生类的六个默认成员函数(以日期类为例)
class Date
{
public:
Date(int year = 1900,int month = 1,int day = 1)
:_year(year)
,_month(month)
,_day(day)
{}
Date(const Date& d)
:_year(d._year)
,_month(d._month)
,_day(d._day)
{}
Date& operator=(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
return *this;
}
~Date()
{}
private:
int _year;
int _month;
int _day;
};
class Time :public Date
{
public:
Time(int hour = 0, int minute = 0, int second = 0)
:Date() //构造函数:子类中从父类继承的成员,采用匿名对象的方式进行构造
, _hour(hour)
, _minute(minute)
, _second(second)
{}
Time(const Time& t)
:Date(t) //“切片”
, _hour(t._hour)
, _minute(t._minute)
, _second(t._second)
{}
Time& operator=(const Time& t) //与父类的operator构成重定义,需要指定Date的作用域调用operator=
{
if (this != &t)
{
Date::operator=(t);
_hour = t._hour;
_minute = t._minute;
_second = t._second;
}
return *this;
}
~Time() //与父类的析构函数也构成重定义,需要指定作用域的调用,但是一般都不需要显示的调用
{
Date::~Date();
}
private:
int _hour;
int _minute;
int _second;
};
3 定义一个不能被继承的类
将构造函数定义为私有的
a.对于父类中私有的成员,不论在哪种继承方式下对于子类而言都是不可见的;
b.子类在构造时,必须先调用父类的构造函数,再构造自己的;
c.不可见的成员是无法调用的,所以该类不能被继承。
d.有一个需要注意的就是:当我们把构造函数定义为私有的,则不能生成该类的实例
e.定义一个静态的公有方法,用于生成该类的实例
//定义一个不能被继承的类
class A
{
public:
static A* GetInstance()
{
return new A();
}
private:
A()
{}
};
int main()
{
A* pa = A::GetInstance();
return 0;
}