继承 Inherit
C++中可重用性
父类 基类
继承 派生
子类 派生类
C++通过继承关系,实现了代码的可重用性。
#include <iostream>
using namespace std;
class Human //父类 共性
{
public:
void eat(string food)
{
cout<<"i am eating"<<food<<endl;
}
};
//public 继承方式
class Teacher:public Human // 子类在父类的基础上增加了新的功能,体现的是个性
{
//访问权限
public:
void tech(string course)
{
cout<<"i am a teacher teach "<<course<<endl;
}
};
class Student:public Human
{
public:
void study(string course)
{
cout<<"i am a student learning "<<course<<endl;
}
};
int main()
{
Teacher t;
t.tech("ttttt");
Student s;
s.eat("aaa");
s.study("c++");
return 0;
}
组合是聚合关系
属于是继承关系
public 继承方式没有影响子类成员的访问方式,影响了父类中的成员在子类中的访问方式
父类中 pub pro pri
子类public继承 public protected inaccess
1、继承后全盘接受,除了析构器和构造器。基类会造成派生类的成员冗余,因此积累是需要设计的。
2、派生类有自己的个性,使派生类有了意义。
student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
using namespace std;
class Student
{
public:
Student(string sn, int ia, float fs)
{
}
void dis();
private:
string name;
int age;
float score;
};
#endif //STUDENT_H
student.cpp
#include "student.h"
#include <iostream>
Student::Student(string sn, int ia, float fs)
:name(sn),age(ia),score(fs)
{
}
void Student::dis()
{
cout<<"name: "<<name<<endl;
cout<<"age: "<<age<<endl;
cout<<"score: "<<score<<endl;
}
main.cpp
#include <iostream>
#include "student.h"
#include "gradient.h"
#include "doctor.h"
using namespace std;
int main()
{
Student s("aa", 30, 100);
s.dis();
cout<<"----------"<<endl;
Graduate g("ggg", 50, 90, 1000);
g.print();
Doctor d("ddd", 23, 200, 5000, "doc");
d.dump();
return 0;
}
Graduate.h
#ifndef GRADUATE_H
#define GRADUATE_H
#include "student.h"
class Graduate:public Student
{
public:
Graduate(string sn, int ia, float fs, double ds);
void print();
private:
double salary;
};
#endif //GRADUATE_H
gradient.cpp
#include "gradient.h"
Gradient::Gradient(string sn, int ia, float fs, double ds)
:Student(sn, ia, fs),salary(ds)
{
//inaccess
// name = sn;
// age = ia;
// score = fs;
}
void Gradient::print()
{
dis(); // name age score 不可见,dis()可用
cout<<"salary: "<<salary<<endl;
}
父类中如果有标配,重载或默认,把默认包含进来
子类中可以不用显式的调用父类的构造器
Doctor.h
#ifndef DOCTOR_H
#define DOCTOR_H
#include "gradient.h"
class Doctor:public Gradient
{
public:
Doctor(string sn, int ia, float fs, double ds, string st);
void dump()
{
print();
cout<<"title: "<<title<<endl;
}
private:
string title;
};
#endif //DOCTOR_H
doctor.cpp
#include "doctor.h"
Doctor::Doctor(string sn, int ia, float fs, double ds, string st)
:Gradient(sn,ia,fs,ds),title(st)
{
}
子类只需对父类负责,不需要对父类的父类负责
类中的子对象 int age, float salary
初始化顺序:父类初始化(父类的父类初始化)、类对象初始化、子类初始化
子类未实现拷贝构造时,会调用父类的拷贝构造器(无论是否实现)
子类一旦实现拷贝构造,则必须显式的调用父类的拷贝构造器
#ifndef STUDENT_H
#define STUDENT_H
class Student
{
public:
Student(string sn, int ia, float fs):
void dis();
Student(const Student& another); // 构造器
Student & operator = (const Student & another);
private:
string name;
int age;
float score;
};
#endif
#include "student.h"
#include <iostream>
using namespace std;
Student::Student(string sn, int ia, float fs)
:name(sn),age(ia),score(fs)
{
}
void Student::dis()
{
cout<<"name: "<<name<<endl;
cout<<"age: "<<age<<endl;
cout<<"score: "<<score<<endl;
}
//定义构造器
Student::Student(const Student& another)
{
this->name = another.name;
this->age = another.age;
this->score= another.score;
}
Student & Student::operator = (const Student & another)
{
if(this == &another)
return *this;
this->name = another.name;
this->age = another.age;
this->score = another.score;
return *this;
}
#ifndef GRADIENT_H
#define GRADIENT_H
#include "student.h"
class Gradient
{
public:
Gradient(string sn, int ia, float fs, double ds);
void print();
Gradient(const & another); // 构造器
Gradient & another = (const Gradient & another);
private:
double salary;
};
#endif
#include "gradient.h"
#include <iostream>
using namespace std;
Gradient::Gradient(string sn, int ia, float fs, double ds)
:Student(sn, ia, fs),salary(ds)
{
}
void Gradient::print()
{
dis();
cout<<"salary: "<<salary<<endl;
}
Gradient::Gradient(const Gradient& another)
:Student(another),salary(another.salary)
{
// Student(another); // 赋值兼容(子类对象(引用或指针),可以赋值给父类(引用或指针))
// this->salary = another.salary;
}
Gradient & Gradient::operator = (const Gradient & another)
{
}
#include <iostream>
#include "student.h"
#include "gradient.h"
using namespace std;
int main()
{
Student s("aa", 200, 100);
s.dis();
cout<<"---------"<<endl;
Gradinet g("gg", 100, 500);
g.print();
return 0;
}
子类中未实现赋值重载时,会调用父类的赋值重载
子类一旦实现赋值重载,不会主动调用父类的赋值重载
子类中会把父类重名的成员shadow
overload 重载:同一作用域,函数名相同,参数列表不同(个数、类型、顺序) 希望发生
shadow 覆盖:父子类中,只要函数名相同即构成shadow 不希望发生
继承方式
成员/继承方式 | public | protected | private |
public | public | protected | private |
protected | protected | protected | inaccessable |
private | inaccessable | inaccessable | inaccessable |
类内部的private protected public 影响访问权限
在继承中,private protected public 父类中的成员在子类中的访问权限
1、在子类中 2、在子类对象中
virtual
从诸多父类中提取公因式,把相同的类成员提到祖父类中,分别令父类虚继承祖父类,子类正常继承自父类,此时子类中无冗余信息,访问亦方便。
#include <iostream>
using namespace std;
class M
{
public:
M(int m):a(m){}
protected:
int a;
};
class A:virtual public M
{
public:
A(int i):M(i){}
};
class B:virtual public M
{
public:
B(int j):M(j){}
};
class C:public A, public B
{
public:
C(int m):A(m), B(m), M(m){}
void func()
{
cout<<a<<endl;
}
};
int main()
{
C c(100);
c.func();
return 0;
}
虚继承
class A: virtual public M
虚基类需要设计和抽象,虚继承是一种继承的扩展
class A
{
A(int i)
{}
};
class B:virtual public A
{
B(int n):A(n){}
};
class C:virtual public A
{
C(int n):A(n){}
};
class D:public B, public C
{
D(int n)
:A(n), B(n), C(n)
{}
};