C++语言-继承

108 阅读2分钟

1、继承的简单实现

class Person {
public:
    char *name;
    int age;
    Person(char *name, int age) : name(name), age(age) {
        cout << "Person " << name << " - " << age << endl;
    }

};

class Boy : Person {
public:
    char *course;
    //调用父类的构造函数
    Boy(char *name, int age, char *course) : Person(name, age) {
        cout << "Boy " << name << " - " << age << "-" << course << endl;
    }

};
    Boy boy("xiaohong", 20, "english");
Person xiaohong - 20
Boy xiaohong - 20-english

子类的构造函数,可以在通过:符号调用父类的构造函数

2、私有继承和公开继承

如果不写关键字,默认是私有继承,私有继承在类外不能访问父类的成员

    //报错,私有继承,类外不能访问父类的成员
    boy.name;
    
  • private和public关键字 private为私有继承、public公开继承,使用public公开继承,在类外就能访问父类的成员
class Boy : public Person {
public:
    char *course;
    //调用父类的构造函数
    Boy(char *name, int age, char *course) : Person(name, age) {
        cout << "Boy " << name << " - " << age << "-" << course << endl;
    }

};
    //不报错,公开继承,类外可以访问父类的成员
    boy.name;

3、使用virtual关键字(虚继承)

virtual关键字解决多个多个父类,成员同名,访问冲突的问题,如下继承关系


class Person {
public:
    char *name;
    int age;
};
class Boy :  public Person {

};
class Gitl :  public Person {
};
class Son :  Boy,Gitl {
};


使用报错

    Son son;
    //报错
    son.name;
    //报错
    son.age;

Boy 和Gitl 都公开继承Person ,Son公开继承了Boy和Gitl ,当Son要访问成员name和age的时候,会报错。因为这种情况是,Son要去向自己的父类获取name和age属性,而因为Boy和Gitl 都拥有一份name和age,因此Son不知道要访问哪一个。大概是如下图的关系: image.png 这种情况我们则可以通过virtual关键字解决:

class Boy : virtual public Person {
};
class Gitl : virtual public Person {
};
class Son : public Boy,Gitl {
};

使用正常

 Son son;
    //正常
    son.name;
    //正常
    son.age;

使用virtual关键字之后,就变成如下关系: 四个类公用了这几个属性。

image.png 以上的情况是属于通过父类间接继承的关系。如果是直接继承关系,多个父类拥有相同的成员,则无法使用virtual关键字来解决,例如:

class Boy {
public:
    char *name;
    int age;
};

class Gitl {
public:
    char *name;
    int age;
};

class Son : virtual public  Gitl,virtual public Boy {
};
int main() {
    Son son;
    //报错
    son.name;
    //报错
    son.age;
}

这个时候我们则需要使用指定类名的方式来解决

    Son son;
//    //正常
    son.Boy::name;
    //正常
    son.Boy::age;

    //正常
    son.Boy::name;
    //正常
    son.Boy::age;