继承
写法
//通过继承创建一个新的学生类
class Student3 :public Student//指定继承的类型
{
public:
Student3(int id, string name, int score) :Student(id, name)//父类的初始化
{
//如果这里没有写父类的初始化,那么会调用父类的无参构造
//不写在上面,写在下面也行:
//this->id = id;
//this->name = name;
this->score = score;//子类的初始化
}
void printS() {
Student::printS();
cout << "score = " << this->score << endl;
}
private:
int score;
};
继承规则
//规则1, 只要是父类中的private成员,不管是什么继承方式,儿子都访问不了
//规则2, 如果是公有(public)继承, 儿子中的访问控制权限保持不变。
//规则3, 如果是保护(protected)继承, 儿子中父亲中除了private成员,其余在儿子中都是protected
//规则4, 如果是私有(private)继承, 儿子中的父亲的除了private成员,其余在二中都是private成员。
继承的兼容性
子类对象可以当作父类对象使用
子类对象可以直接赋值给父类对象
子类对象可以直接初始化父类对象
父类指针可以直接指向子类对象
父类引用可以直接引用子类对象
(形参中传一个父类的引用,使用的时候就可以传子类对象了)
构造顺序
在调用子类的构造函数时候,一定会调用父类的构造函数
父类先构造,子类后构造。
父类和子类的变量同名
- 子类创造的对象只会调用子类的属性
- 如果父类的属性在public,和protected中的话,还能用作用域调出来,如果是private的话,就再也看不到了
代码实例
#include <iostream>
class parent {
public:
parent(int num) {
this->a = num;
}
int a;
};
class child : public parent {
public:
child(int number, int num) : parent(num) {
this->a = number;
}
void print() {
std::cout << this->a << std::endl;
std::cout << parent::a << std::endl;
}
int a;
};
int main() {
child B(10, 20);
B.print();
std::cout << "Hello, World!" << std::endl;
return 0;
}
static变量
static变量在父类和子类中是共享的,也就是同一个变量。
虚继承
为了防止菱形继承(子类继承的两个父类来自于同一个爷爷类),所以在多继承的时候,在父类和爷爷类之间加个关键字,virtual
class Bed:virtual public Furniture
父类和子类的函数同名
#include <iostream>
using namespace std;
class parent {
public:
explicit parent(int num) {
this->a = num;
}
void run (){
cout << "跑父" << endl;
}
protected:
int a;
};
class child : public parent {
public:
child(int number, int num) : parent(num) {
this->a = number;
}
void run (){
cout << "跑子" << endl;
}
int a;
};
int main() {
child B(10, 20);
B.run(); //子类对象还是会调用子类方法
parent *p = new parent (1);
p = &B;
p->run();//父类指针指向子类对象,调用子类方法时,调用的是父类的方法。。。这就出现了问题。。。
std::cout << "Hello, World!" << std::endl;
return 0;
}
多态
多态发生的三个必要条件:
- 要有继承。
- 要有虚函数重写。
- 父类指针或引用 指向 子类对象。
virtual void run (){
cout << "跑父" << endl;
}
父类写成虚函数,子类的同名就是虚函数重写,这样调用的就是子类的函数了。
记得父类的虚构函数,也要写成虚函数。