c++之继承
为什么需要继承?
继承允许依据一个类来定义一个类,使得创建和维护一个应用程序更容易,提高效率。
#include<iostream>
using namespace std;
class IndexPage{
public:
//网页头部
void Header(){
cout << "网页头部!" << endl;
}
//网页左侧菜单
void LeftNavigation(){
cout << "左侧导航菜单!" << endl;
}
//网页主体部分
void MainBody(){
cout << "首页网页主题内容!" << endl;
}
//网页底部
void Footer(){
cout << "网页底部!" << endl;
}
private:
string mTitle; //网页标题
};
//如果不使用继承,那么定义新闻页类,需要重新写一遍已经有的代码
//class NewsPage{
//public:
// //网页头部
// void Header(){
// cout << "网页头部!" << endl;
// }
// //网页左侧菜单
// void LeftNavigation(){
// cout << "左侧导航菜单!" << endl;
// }
// //网页主体部分
// void MainBody(){
// cout << "新闻网页主体内容!" << endl;
// }
// //网页底部
// void Footer(){
// cout << "网页底部!" << endl;
// }
// private:
// string mTitle; //网页标题
//};
//使用继承,可复用已有的代码
class NewsPage:public IndexPage
{
public:
void MainBody()
{
cout << "新闻网页主体 "<<endl;
}
};
int main()
{
NewsPage p;
p.Footer();
p.MainBody();
return 0;
}
派生类定义:
//基类
class A{
public:
int mA;
protected:
int mB;
private:
int mC;
};
//1. 公有(public)继承
class B : public A{
public:
void PrintB(){
cout << mA << endl; //可访问基类public属性
cout << mB << endl; //可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
class SubB : public B{
void PrintSubB(){
cout << mA << endl; //可访问基类public属性
cout << mB << endl; //可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
void test01(){
B b;
cout << b.mA << endl; //可访问基类public属性
//cout << b.mB << endl; //不可访问基类protected属性
//cout << b.mC << endl; //不可访问基类private属性
}
//2. 私有(private)继承
class C : private A{
public:
void PrintC(){
cout << mA << endl; //可访问基类public属性
cout << mB << endl; //可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
class SubC : public C{
void PrintSubC(){
//cout << mA << endl; //不可访问基类public属性
//cout << mB << endl; //不可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
void test02(){
C c;
//cout << c.mA << endl; //不可访问基类public属性
//cout << c.mB << endl; //不可访问基类protected属性
//cout << c.mC << endl; //不可访问基类private属性
}
//3. 保护(protected)继承
class D : protected A{
public:
void PrintD(){
cout << mA << endl; //可访问基类public属性
cout << mB << endl; //可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
class SubD : public D{
void PrintD(){
cout << mA << endl; //可访问基类public属性
cout << mB << endl; //可访问基类protected属性
//cout << mC << endl; //不可访问基类private属性
}
};
void test03(){
D d;
//cout << d.mA << endl; //不可访问基类public属性
//cout << d.mB << endl; //不可访问基类protected属性
//cout << d.mC << endl; //不可访问基类private属性
}
在继承过程中如果遇到同名成员函数的话该怎么办?
1、当子类成员和父类成员同名时,子类依然从父类继承同名成员。
2、如果子类有成员和父类同名,子类访问其成员默认访问子类的成员(就近原则)。
3、子类通过作用域::进行同名成员的区分。
#include<iostream>
using namespace std;
class Base{
public:
Base():mParam(0){}
void Print(){ cout << mParam << endl; }
public:
int mParam;
};
class Derived : public Base{
public:
Derived():mParam(10){}
void Print(){
//在派生类中使用和基类的同名成员,显示使用类名限定符
cout << Base::mParam << endl;
cout << mParam << endl;
}
//返回基类重名成员
int& getBaseParam(){ return Base::mParam; }
public:
int mParam;
};
int main(){
Derived derived;
//派生类和基类成员属性重名,子类访问成员默认是子类成员
cout << derived.mParam << endl; //10
derived.Print();
//类外如何获得基类重名成员属性
derived.getBaseParam() = 100;
cout << "Base:mParam:" << derived.getBaseParam() << endl;
return 0;
}
如果重新定义基类中的重载函数,会发生什么?
class Base{
public:
void func1(){
cout << "Base::void func1()" << endl;
};
void func1(int param){
cout << "Base::void func1(int param)" << endl;
}
void myfunc(){
cout << "Base::void myfunc()" << endl;
}
};
class Derived1 : public Base{
public:
void myfunc(){
cout << "Derived1::void myfunc()" << endl;
}
};
class Derived2 : public Base{
public:
//改变成员函数的参数列表
void func1(int param1, int param2){
cout << "Derived2::void func1(int param1,int param2)" << endl;
};
};
class Derived3 : public Base{
public:
//改变成员函数的返回值
int func1(int param){
cout << "Derived3::int func1(int param)" << endl;
return 0;
}
};
int main(){
Derived1 derived1;
derived1.func1();
derived1.func1(20);
derived1.myfunc();
cout << "-------------" << endl;
Derived2 derived2;
//derived2.func1(); //func1被隐藏
//derived2.func1(20); //func2被隐藏
derived2.func1(10,20); //重载func1之后,基类的函数被隐藏
derived2.myfunc();
cout << "-------------" << endl;
Derived3 derived3;
//derived3.func1(); 没有重新定义的重载版本被隐藏
derived3.func1(20);
derived3.myfunc();
return 0;
}
任何时候重新定义基类中的一个重载函数,在新类中所有的其他版本将被自动隐藏.
虚继承(解决二义性问题)
class BigBase{
public:
BigBase(){ mParam = 0; }
void func(){ cout << "BigBase::func" << endl; }
public:
int mParam;
};
class Base1 : public BigBase{};
class Base2 : public BigBase{};
class Derived : public Base1, public Base2{};
int main(){
Derived derived;
//1. 对“func”的访问不明确
//derived.func();
//cout << derived.mParam << endl;
cout << "derived.Base1::mParam:" << derived.Base1::mParam << endl;
cout << "derived.Base2::mParam:" << derived.Base2::mParam << endl;
//2. 重复继承
cout << "Derived size:" << sizeof(Derived) << endl; //8
return 0;
}
采用虚基类
class BigBase{
public:
BigBase(){ mParam = 0; }
void func(){ cout << "BigBase::func" << endl; }
public:
int mParam;
};
class Base1 : virtual public BigBase{};
class Base2 : virtual public BigBase{};
class Derived : public Base1, public Base2{};
int main(){
Derived derived;
//二义性问题解决
derived.func();
cout << derived.mParam << endl;
//输出结果:24
cout << "Derived size:" << sizeof(Derived) << endl;
return 0;
}
虚继承中增加了一个虚指针。