C++之继承

多级继承

一个派生类继承了基类除构造函数,拷贝构造函数,析构函数,重载运算符和友元函数所有的成员函数和成员变量。

#include <iostream>

using namespace std;

class A {
public:
    void set_width(int w);

    void set_height(int h);

    void set_length(int l);

    void set_name(char *n);

    void set_sport(char *st);

    char *get_sport();

protected:
    int height;
    int width;
    char *name;
    int length;

private:
    char *sport;
};

void A::set_width(int w) { width = w; }

void A::set_height(int h) { height = h; }

void A::set_length(int l) { length = l; }

void A::set_name(char *n) { name = n; }

void A::set_sport(char *st) { sport = st; }

char *A::get_sport() { return sport; }

class B : public A {
public:
    void set_score(int scores);

protected:
    int score;
};

void B::set_score(int scores) { score = scores; }

class C : public B {
public:
    void display();
};

void C::display() {
    cout << height << width << length << name << get_sport() << score << endl;
}

int main() {
    system("chcp 65001");
    C c;
    char name[] = "阿吉";
    char sport[] = "健身";
    c.set_height(10);
    c.set_width(20);
    c.set_length(30);
    c.set_score(50);
    c.set_sport(sport);
    c.set_name(name);
    c.display();
    return 0;
}
输出:
Active code page: 65001
102030阿吉健身50

继承有单继承和多继承,在java中只能够单继承,也就是只能继承一个基类,而在C++中可以多重继承,也就是继承多个基类,上述程序中A就是一个基类,而B是A的派生类,C是B的派生类,因为B继承于A,所以C也是A的派生类。派生类可以继承除private修饰符以外的所有成员变量和成员函数。继承形式: class X : public(private或protected)Y {};Y前面的修饰符指定了派生类X中的访问级别,当继承基类是public的时候,基类中的public在派生类中按照public访问,protected按照protected访问,private不允许访问,也就是在派生类中隐藏了。 若是protected,那么public在派生类中按照protected访问(权限降低),protected按照protected访问,private不允许访问。若是private,那么public在派生类中按照private访问(权限降到最低),protected按照private访问,private不能访问。可以看到无论继承基类的修饰符是public,protected,还是private的,基类中声明的private的成员变量和成员函数都不能访问,在派生类中隐藏。

调用基类的构造函数

#include <iostream>

using namespace std;

class Teacher {
public:
    Teacher(char *name, int age);

protected:
    char *name;
    int age;
};

Teacher::Teacher(char *name, int age) : name(name), age(age) {

}

class Student : public Teacher {
public:
    Student(char *name, int age, float score);

    void display();

private:
    float score;
};

Student::Student(char *name, int age, float score) : Teacher(name, age), score(score) {}

void Student::display() {
    cout << name << "的年龄是" << age << ",成绩是" << score << endl;
}

int main() {
    system("chcp 65001");
    char name[] = "阿吉";
    int age = 20;
    int score = 100;
    Student stu(name, age, score);
    stu.display();
    return 0;
}
输出:
Active code page: 65001
阿吉的年龄是20,成绩是100

派生类构造函数总是先调用基类构造函数再执行其他代码(包括参数初始化以及函数体的代码),参数初始化指的是this.score = score;子类中的成员变量初始化。注意基类构造函数不会被继承,不能当做普通的成员函数来调用。换句话说,只能将基类构造函数的调用放在函数头部,不能放在函数体中。另外,函数头部是对基类构造函数的调用,而不是声明,所以括号里的参数是实参,它们不但可以是派生类构造函数参数列表中的参数,还可以是局部变量、常量。比如上述程序中的Student::Student(char *name, int age, float score) : Teacher(name, age), score(score) {}中Teacher(name,age)就是在头部调用的基类的构造函数,name,age是传入的实参。

构造函数的调用顺序

通过上面的程序可以发现,程序总是先调用基类的构造函数,再调用派生类的构造函数,若是多级继承(上述第一个程序),那么系统在创建C类对象时,构造函数会隐式的先调用A()再调用B()最后再调用C(),此时的A()代表的是A的构造函数,下同。这是按照自顶向下的顺序调用构造函数。注意定义派生类构造函数的时候,只能直接调用它直接继承的基类的构造函数,不能调用间接基类的构造函数,也就是说在C的头部可以直接调用B(),但是不能调用A(). 这样做的目的是为了节省内存,避免多次创建A()。

基类构造函数调用规则

C++规定创建派生类对象时必须要调用基类的构造函数,在定义派生类构造函数时最好要指明基类构造函数,若没有指明,则调用的是基类默认的构造函数(无参构造函数),若基类中含有带参的构造函数,则必须在定义派生类构造函数时显示调用基类构造函数,否则会出问题。

#include <iostream>

using namespace std;

class A {
public:
    A(int w);

private:
    int width;
};

A::A(int w) : width(w) {}

class B : public A {
public:
    B(int l, int w);

private:
    int length;
};
//若不指明调用基类的A(w),则会报错
//若在基类A中定义了A(){}无参构造函数,那么B()可以定义为:
//B::B(int l,int w):length(l){}这是隐式调用了基类的A()
B::B(int l, int w) : length(l), A(w) {}

int main() {
	//若没有23行的代码,则会报错
    B b(1, 2);
    return 0;
}

继承中的析构函数

在C++中基类的析构函数和构造函数都不能被派生类继承,和构造函数不同的是,在派生类头部不用显示的调用基类的析构函数,因为每个类只有一个析构函数,程序会自动调用。
析构函数和构造函数在执行顺序上也有区别,析构函数会先销毁派生类的对象,再销毁基类的对象,这点和构造函数的执行顺序相反。

#include <iostream>

using namespace std;

class A {
public:
    A(int w);

    A();

    ~A();

private:
    int width;
};

A::A(int w) : width(w) { cout << "A structure" << endl; }

A::A() { cout << "A no parameters structure" << endl; }

A::~A() { cout << "A destructed" << endl; }

class B : public A {
public:
    B(int l, int w);

    ~B();

private:
    int length;
};

B::B(int l, int w) : length(l) { cout << "B structure" << endl; }

B::~B() { cout << "B destructed" << endl; }

int main() {
    B b(1, 2);
    return 0;
}
输出:
A no parameters structure //基类A()先执行
B structure//派生类B() 后执行
B destructed //派生类~B()先执行
A destructed //基类~A()后执行

多重继承

#include <iostream>

using namespace std;

class A {
public:
    A(int w, int h);

    ~A();

    int get_width();

    int get_height();

private:
    int width;
    int height;
};

A::A(int w, int h) : width(w), height(h) { cout << "A constructed" << endl; }

A::~A() { cout << "A destructed" << endl; }

int A::get_width() { return this->width; }

int A::get_height() { return this->height; }

class B {
public:
    B(int len, int ar);

    ~B();

    int get_length();

    int get_area();

private:
    int length;
    int area;
};

B::B(int len, int ar) : length(len), area(ar) { cout << "B constructed" << endl; }

B::~B() { cout << "B destructed" << endl; }

int B::get_length() { return this->length; }

int B::get_area() { return this->area; }

class C : public A, public B {
public:
    C(int w, int h, int l, int a, int c);

    ~C();

    int get_con();

    void show();

private:
    int con;
};

//派生类对象定义,故意将调用B和A的顺序弄反,结果还是根据继承时的顺序来执行基类的构造函数
C::C(int w, int h, int l, int a, int c) : B(l, a), A(w, h), con(c) {
    cout << "C constructed" << endl;
}

C::~C() { cout << "C destructed" << endl; }

int C::get_con() { return this->con; }

void C::show() {
    cout << get_width() << "," << get_height() << ","
         << get_length() << "," << get_area() << "," << get_con() << endl;
}

int main() {
    C c(1, 2, 3, 4, 5);
    c.show();
}
输出:
A constructed
B constructed
C constructed
1,2,3,4,5
C destructed
B destructed
A destructed

C++中多继承的形式是class X:public A,private B,protected C{};指的是C按照public继承A,private继承B,protected继承C。关于这三种修饰符的区别上面已提过,这里不再赘述。
上述程序中,我们使用派生类C分别以public的形式继承了基类A,基类B,这是一种多继承的方式,这里相当于是声明了C的基类,和继承基类的顺序,所以定义派生类C构造函数的时候,调用基类的顺序并不能决定基类构造函数被调用的顺序,基类构造函数的优先调用取决于继承声明时的顺序,故A()比B()先调用。 派生类析构函数先于基类的析构函数被销毁,先创建的基类构造函数对象后销毁,这和单继承是一样的。

命名冲突

C++多继承中,由于派生类继承多个基类,难免会出现部分基类中有相同命名的成员函数,若要调用这相同命名的成员函数,那么就该在成员函数前使用类名::的形式用以区分。下列程序中的基类A和B中就存在相同命名的成员函数show(),在派生类C中区分的方式为A::show();B::show();

#include <iostream>

using namespace std;

class A {
public:
    A(int w, int h);

    ~A();

    int get_width();

    int get_height();

    void show();

private:
    int width;
    int height;
};

A::A(int w, int h) : width(w), height(h) { cout << "A constructed" << endl; }

A::~A() { cout << "A destructed" << endl; }

int A::get_width() { return this->width; }

int A::get_height() { return this->height; }

void A::show() { cout << "this is A.show()" << endl; }

class B {
public:
    B(int len, int ar);

    ~B();

    int get_length();

    int get_area();

    void show();

private:
    int length;
    int area;
};

B::B(int len, int ar) : length(len), area(ar) { cout << "B constructed" << endl; }

B::~B() { cout << "B destructed" << endl; }

int B::get_length() { return this->length; }

int B::get_area() { return this->area; }

void B::show() { cout << "this is B.show()" << endl; }

class C : public A, public B {
public:
    C(int w, int h, int l, int a, int c);

    ~C();

    int get_con();

    void show();

private:
    int con;
};

//派生类对象定义,故意将调用B和A的顺序弄反,结果还是根据继承时的顺序来执行基类的构造函数
C::C(int w, int h, int l, int a, int c) : B(l, a), A(w, h), con(c) {
    cout << "C constructed" << endl;
}

C::~C() { cout << "C destructed" << endl; }

int C::get_con() { return this->con; }

void C::show() {
    cout << get_width() << "," << get_height() << ","
         << get_length() << "," << get_area() << "," << get_con() << endl;
    A::show();
    B::show();
}

int main() {
    C c(1, 2, 3, 4, 5);
    c.show();
}
输出:
A constructed
B constructed
C constructed
1,2,3,4,5
this is A.show()
this is B.show()
C destructed
B destructed
A destructed
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值