C++继承
继承遗传学中继承概念,继承的写法,以及继承中的权限问题,继承中的构造函数写法
继承的实质就是父类有的属性在子类中也存在一份。只是根据继承方式不同,在子类中权限的体现不同。
继承:子类没有新的属性或者行为产生
- 父类
- 子类
派生:派生类中有新的属性产生
- 基类
- 派生类
单继承
只有父类的继承称之为单继承
写法
class 父类 { }; class 子类:继承方式 父类名 { }; //继承方式就是权限限定词 //公有继承: public //保护继承: protected //私有继承: private
继承中权限问题
public |
protected |
private |
|
public继承 |
public |
protected |
不可访问 |
protected继承 |
protected |
protected |
不可访问 |
private继承 |
private |
private |
不可访问 |
综上: 权限限定词只会增强权限(public:最低权限 private:最高权限)
#include <iostream> #include <string> using namespace std; //父类 class MM { public: string getName() { return name; } void print() { cout << name << "\t" << age << endl; } protected: int age=18; private: string name="默认"; }; //子类 //公有继承 class Boy :public MM { public: //print() void printBoy() { //cout << name << endl; 不可能访问 cout << age << endl; print(); } protected: //int age private: //string name; 不能访问 }; //保护继承 class Girl :protected MM { public: void printGirl() { cout << age << endl; print(); } protected: //void print() //int age; private: //string name; }; //私有继承 class Son :private MM { public: void printSon() { print(); cout << age << endl; //cout << name << endl; //父类的私有属性子类不能使用 //只能间接调用父类的非私有方法访问 cout << getName() << endl; } protected: private: //void print(); //int age; //string name; }; int main() { Boy boy; boy.print(); boy.printBoy(); Girl girl; //girl.print(); //无法访问 girl.printGirl(); Son son; son.printSon(); return 0; }
注意点:
- 继承的属性无论被继承多少次,都存在, A 被B继承 B被C继承 C被D继承 D包含ABC中所有属性
- 继承不易过多继承,导致子类臃肿
- 私有继承可以阻断父类属性被孙子类去使用(断子绝孙)
继承中构造函数写法
- 写法:子类必须先构造父类对象(子类必须调用父类的构造函数) ,调用父类的构造函数必须采用初始化参数列表
- 构造和析构顺序问题
#include <iostream> #include <string> using namespace std; class A { public: A() { cout << a; } A(string a):a(a) { cout << a; } ~A() { cout << a; } protected: string a="A"; }; class B :public A { public: B() //就算没写,也会调用父类的无参构造函数 { cout << b; } //子类完整写法: 除了初始化自身数据,还需要初始化父类数据 B(string a, string b) :A(a) { this->b = b; //自身属性可以采用初始化列表 cout << b; } void print() { cout << a; cout << b; } ~B() { cout << b; } protected: string b = "B"; }; class C :public B { public: C(string a, string b, string c) :B(a, b), c(c) { cout << c; } void print() { cout << a << b << c << endl; } ~C() { cout << c; } protected: string c; }; int main() { { B b; cout << endl; B object("A", "B"); cout << endl; object.print(); cout << endl; C c("A","B","C"); cout << endl; c.print(); } cout << endl; { cout << "构造和析构顺序问题:" << endl; C cobject("A", "B", "C"); //ABCCBA } return 0; }
多继承
多继承就是存在两个以及两个以上父类
- 权限问题和构造函数和单继承一样的
#include <iostream> #include <string> using namespace std; class Father { public: Father(string FFName) :FFName(FFName) {} protected: string FFName; }; class Monther { public: Monther(string MFName) :MFName(MFName) {} protected: string MFName; }; class Son :public Father, public Monther { public: Son(string FFName, string MFName, string SSName) :Father(FFName),Monther(MFName) { this->SFName = FFName + MFName; this->SSName = SSName; } void print() { cout << FFName << endl; cout << MFName << endl; cout << this->SFName + this->SSName << endl; } protected: string SFName; string SSName; }; int main() { Son son("李","田","大牛"); son.print(); return 0; }
菱形继承
菱形继承是因为多继承存在问题而衍生的继承方式(菱形继承就是虚继承)
(题目可能会出现,但是自己写代码不会出现)
#include <iostream> #include <string> using namespace std; class A { public: A(int a) :a(a) {} int a=666; }; class B :virtual public A { public: B(int a) :A(a) {} }; class C :virtual public A { public: C(int a) :A(a) {} }; class D :public C, public B //多继承构造顺序只和这个地方顺序(继承顺序)有关 { public: D(int a) : C(14), B(12) ,A(a) //子类必须调用爷爷构造函数 { } void print() { cout << A::a << endl; cout << B::a << endl; cout << C::a << endl; } }; int main() { D dobject(23); dobject.print(); return 0; }
继承中同名问题
- 数据成员同名
- 成员函数同名
#include <iostream> #include <string> using namespace std; class MM { public: MM(string name) :name(name) {} void print() { cout << "-------------------------" << endl; cout << "MM::name" << endl; cout << "-------------------------" << endl; } protected: string name; }; class Son :public MM { public: Son() :name("Son"), MM("MM") { } void print() { cout << "-------------------------" << endl; cout << "Son::name" << endl; //No.1 不写任何标识 ,就近原则 cout << name << endl; //No.2 可以用类名 cout << MM::name << endl; cout << "-------------------------" << endl; } protected: string name; }; void printInfo(MM* p) { p->print(); } int main() { //对象访问: //No.1 不写任何标识 ,就近原则 Son son; son.print(); son.MM::print(); son.Son::print(); MM mm("MM"); mm.print(); //指针访问 //正常初始化访问 cout << "正常初始化指针访问" << endl; Son* pSon = new Son; pSon->print(); MM* pMM = new MM("MM"); pMM->print(); //非正常初始化访问 //1.1 父类指针用子类对象初始化 //在没有写任何修饰词的,看指针类型 MM* pFather = new Son; pFather->print(); //调用那个函数? //1.2 子类指针被父类对象初始化,危险,一般不这样做 //Son* pp = new MM("MM"); //错误的 Son* pp = NULL; pp = static_cast<Son*>(&mm); //强制类型转换类似C语言强制 //pp->print(); //程序中断,没办法执行 cout << "当父类指针成为函数参数时候,传参子类和父类对象通用" << endl; printInfo(pMM); printInfo(pSon); return 0; }