继承:
使子类(派生类)拥有与父类(基类)相同的成员,以节约代码量。
1.继承的基本语法:
class 子类名:继承方式 父类名{} ;
例:
class father
{
public:
int money;
int debt;
};
class son :public father
{
private:
int id;
};
int main()
{
son s;
s.debt = 20;//可以访问父类中的成员
}
从父类继承来的成员表现其共性,子类独有的成员表现其个性。
2.继承方式:
继承方式共有三种:
公共继承:public;保护继承:protected;私有继承:private。
总结:
1.父类中私有成员子类一定无法访问。
2.public > protected > private
父类中更公开的权限,如果比继承方式还要公开,则降为继承方式对应权限。
3.继承中的对象模型:
如果父类中的私有成员,子类访问不到,那这个成员是否属于子类呢?
看下面代码:
//继承中的对象模型
class father
{
public:
int m_A;
protected:
int m_B;
private:
int m_C;
};
class Son :public father
{
public:
int m_D;
};
int main()
{
cout << sizeof(Son) << endl;//结果为16
return 0;
}
可以看到结果为16,说明父类中非静态的成员属性,都会被子类继承下去,只是父类中私有属性被隐藏了。
4.继承中的构造和析构顺序:
先构造父类,再构造子类;先析构子类,再析构父类
//继承中的构造和析构顺序
class father
{
public:
father()
{
cout << "father构造函数" << endl;
}
~father()
{
cout << "father析构函数" << endl;
}
};
class Son :public father
{
public:
Son()
{
cout << "Son构造函数" << endl;
}
~Son()
{
cout << "Son析构函数" << endl;
}
};
int main()
{
Son s;
}
5.继承同名成员处理方式:
访问子类同名成员,直接访问即可;
访问父类同名成员,需加作用域;
class father
{
public:
father()
{
m_A = 100;
}
int m_A;
};
class Son :public father
{
public:
Son()
{
m_A = 200;
}
int m_A;
};
int main()
{
Son s;
cout << s.m_A << endl;//200
cout << s.father::m_A << endl;//访问父类,100
}
注:如果子类中出现了和父类同名成员函数,子类的桶面成员会隐藏掉父类中所有的同名成员函数,包括重载。
class father
{
public:
void func()
{
cout << "father::func调用" << endl;
}
void func(int a)
{
cout << "father::func(int a)调用" << endl;
}
};
class Son :public father
{
public:
void func()
{
cout << "son::func调用" << endl;
}
};
int main()
{
Son s;
s.func();
s.func(100);//报错,父类重载同名函数被隐藏,需加作用域
}
6.继承同名静态成员处理方式:
class Father
{
public:
static int m_A;
};
int Father::m_A = 100;
class Son :public Father
{
public:
static int m_A;
};
int Son::m_A = 200;
(1)通过对象访问:
原理同上
int main()
{
Son s;
cout << s.m_A << endl;//200
cout << s.Father::m_A << endl;//100
return 0;
}
(2)通过类名进行访问:
Son : : Father : : m_A;
//第一个 : : 代表通过类名的方式访问,第二个 : : 代表访问父类作用域下的成员
int main()
{
Son s;
cout << Son::m_A << endl;//200
//第一个::代表通过类名的方式访问,第二个::代表访问父类作用域下的成员
cout << Son::Father::m_A << endl;//100
return 0;
}
7.多继承语法:
class 子类 : 继承方式 父类1,继承方式 父类2 ......
(注:会有多个父类有同名成员的问题,不建议使用)
class Father1
{
public:
int A;
};
class Father2
{
public:
int B;
};
class Son :public Father1, public Father2
{
int C;
};
int main()
{
cout << sizeof(Son) << endl;//3个int类型,结果为12
return 0;
}
同名问题:需加作用域加以区分。
8.菱形继承:
两个子类继承同一个父类,又有一个类继承这两个子类,这种继承方式叫做菱形继承。
(1)菱形继承的问题:
1.两个子类都继承了父类的属性,当“孙子类”调用数据时,会产生二义性。
2.孙子类继承自两个子类的相同属性,只需一份即可。
(2)解决方法:虚继承
1.语法:在两个子类的继承方式前加上关键字 virtual ,父类称为虚基类。
2.作用:使两个子类继承的实际为指针,创建孙子类时两个子类的指针都指向同一块数据。
class Father
{
public:
int m_age;
};
class Son1 :virtual public Father{};
class Son2 :virtual public Father{};
class GrandSon :public Son1, public Son2{};
void test01()
{
GrandSon p;
p.Son1::m_age = 18;
p.Son2::m_age = 20;
cout << p.m_age << endl;//虚继承后,只有一份数据,结果为20
cout << p.Son1::m_age << endl;//20
cout << p.Son2::m_age << endl;//20
}