C++学习(四)

   继承与派生:

{

        继承 即从已有类基础上创建新类 新类可从一个或多个类继承数据成员和成员函数

        可重新定义或添加新的数据 可改变基类成员在派生类中的访问属性

        已有类称为基类或父类 新类称为派生类或子类

        派生类对基类成员的访问:

            内部访问:由派生类中新增的成员函数对基类继承来的成员进行访问

            对象访问:在派生类的外部 通过派生类的对象对基类继承来的成员进行访问

        一般格式:{

            派生类名(参数表) : 基类名(参数表)

            {

                派生类新增数据成员初始化

            }

            含子对象构造函数:

            派生类名(参数总表) : 基类名(参数表0), 子对象1(参数表1), ... , 子对象n(参数表n)

            {

                派生类新增成员初始化

            }

        }

        派生类可声明与基类成员同名的成员 在无虚函数时 若派生类中定义了与基类成员同名的成员

        则派生类成员覆盖基类的同名成员 在派生类中使用该名字代表访问派生类中声明的成员

        若想在派生类中使用与基类同名的成员 须在成员名之前加上 基类名及作用域标识符'::' 即:{

            基类名::函数名(参数表);

            eg:{

                class B : private A{

                    private:

                        int Bb;

                    public:

                        B(int a, int b) : A(a) {

                            Bb = b;

                        }

                        A::show;    // 访问声明

                };

            }

        }

        数据成员也可以使用访问声明

        访问声明中只含不带类型和参数的函数名或变量名

        访问声明不能改变成员在基类中的访问属性

        对于基类的重载函数名 访问声明将对基类中所有同名函数其起作用

        多继承:{

            形式如下:

                class 派生类名 : 继承方式1 基类名1, ... , 继承方式n 基类名n

                {

                    ...

                }

            默认继承方式为private

        }

#include <iostream>

using namespace std;

class Person{
    private:
        string name;
        int age;
        int number;
    public:
        Person(string na, int ag, int num) {
            name = na;
            age = ag;
            number = num;
        }

        ~Person() {
        }

        void show_person(void) {
            cout << "name is: " << name << " age is: " << age << " number is: " << number << endl;
        }
};

class Student: public Person{
    private:
        string major;
    public:
        Student(string na, int ag, int num, string maj) : Person(na, ag, num) {
            major = maj;
        }

        ~Student() {
        }

        void show_student(void) {
            Person::show_person();
            cout << " major is: " << major << endl;
        }
};

int main()
{
    Student stu("Tom", 18, 2019001, "Computer Science");
    stu.show_student();

    return 0;
}

        虚基类:{

            一般形式 :

                class 派生类名 : virtual 继承方式 类名{

                ...

                };

        }

        赋值兼容规则:{    '条件派生类从其基类公有派生'

            在任何需要基类对象的地方 都可用子类的对象代替 但只能使用从基类继承来的成员

            假设有如下类:{

                class Base{

                    ...

                };

                class Derived : public Base{

                    ...

                };

            }

            派生类对象可以赋值给基类对象,即用派生类对象中从基类继承来的数据成员,逐个赋值给基类对象的数据成员

            eg:{

                Base b;

                Derived d;

                b = d;

            }

            派生类对象可以初始化基类对象的引用

            eg:{

                Derived d;

                Base &b = d;

            }

            派生类对象的地址可以赋值给指向基类对象的指针

            eg:{

                Derived d;

                Base *p = &d;

            }

        }

   }

#include <iostream>

using namespace std;

class Base{
    protected:
        int a;
    public:
        Base() {
            a = 5;
            cout << "Base = " << a << endl;
        }
};

class Base1: virtual public Base{
    public:
        Base1() {
            a += 5;
            cout << "Base1 = " << a << endl;

        }
};

class Base2: virtual public Base{
    public:
        Base2() {
            a += 20;
            cout << "Base2 = " << a << endl;
        }
};

class Derived: public Base1, public Base2{
    public:
        Derived() {
            cout << "the Base1 = " << Base1::a << endl;
            cout << "the Base2 = " << Base2::a << endl;
        }
};

int main()
{
    Derived objd;

    return 0;
}

   多态性与虚函数:

{                                   '一个接口,多种方法'

        即不同对象收到相同消息 产生不同动作

        静态连编就是在编译阶段完成的连编 动态连编时运行阶段完成的

        编译时的多态是通过静态连编来实现 运行时的多态是用动态连编实现

        编译时多态性主要是通过函数重载和运算符重载实现  运行时多态性主要是通过虚函数来实现

        虚函数:{

            形式如下:  

              virtual 返回值类型 函数名(参数表)

              {

                      函数体

              }

            在基类中的某个成员函数被声明为虚函数后,此虚函数就可以在一个或多个派生类中被重新定义

            虚函数在派生类中重新定义时 其函数原型 包括返回类型 函数名 参数个数 参数类型的顺序 都必须与基类中的原型完全相同

            若在派生类中 没有用virtual显示给出虚函数说明 则根据以下规则判断 该函数是否为虚函数:

                与基类的虚函数是否有相同的名称 参数个数以及对应的参数类型 返回类型或者满足赋值兼容的指针 引用型的返回类型

            通过定义虚函数来使用多态性机制时 派生类必须从它的基类公有派生

            虚函数必须是其所在类的成员函数 而不能是友元函数 也不能是静态成员函数 因为虚函数调用要靠特定的对象来决定该激活哪个函数

            内联函数不能是虚函数 内联函数是不能在运行中动态确定其位置的

            构造函数不能是虚函数 析构函数可以是虚函数 且通常说明为虚函数

            在一个派生类中重新定义基类的虚函数是函数重载的另一种形式

        }

#include <iostream>
#include <string>
using namespace std;

class Family{
    private:
        string flower;
    public:
        Family(string name = "flowers") : flower(name) {
        }
        string get_flower(void) {
            return flower;
        }

        virtual void like_flower(void) {
            cout << "they like different flowers" << endl;
        }
};

class Child: public Family{
    public:
        Child(string name = "camellia"): Family(name) {
        }
        void like_flower(void) {
            cout << " she likes " << get_flower() << endl;
        }
};

class Parent: public Family{
    public:
        Parent(string name = "rose"): Family(name) {
        }
        void like_flower(void) {
            cout << " he likes  " << get_flower() << endl;
        }
};

int main()
{
    Family *F;
    Family y;
    Child c;
    Parent p1;
    F = &y;
    F->like_flower();
    F = &c;
    F->like_flower();
    F = &p1;
    F->like_flower();

    return 0;
}

        虚析构函数:{

            virtual ~类名() {

                ...

            }

            如果将基类的析构函数定义为虚函数 由该类所派生的所有派生类的析构函数也都自动成为虚函数

        }

#include <iostream>
#include <string>

using namespace std;

class Base{
    public:
        // ~Base() {         //此时系统仅调用基类的析构函数
        virtual ~Base() {
            cout << "调用基类Base的析构函数" << endl;
        }
};

class Derived: public Base{
    public:
        ~Derived() {
            cout << "调用派生类Derived的析构函数" << endl;
        }
};


int main()
{
    Base *p;
    p = new Derived();
    delete p;

    return 0;
}

        纯虚函数 {

            纯虚函数是在声明虚函数时被'初始化为0的函数' 声明纯虚函数的一般形式如下

                virtual 返回值类型 函数名(参数表) = 0;

            声明为纯虚函数后 基类中就不再给出程序的实现部分 纯虚函数的作用是在基类中为其派生类保留一个函数的名字 以便派生类根据需要重新定义

        }

        抽象类 {

            如果一个类至少有一个纯虚函数 那么就称该类为抽象类

                由于抽象类中至少包含一个没有定义功能的纯虚函数 抽象类只能作为其他类的基类来使用 不能建立抽象类对象

                不允许从具体类派生出抽象类 具体类即 不包含纯虚函数的普通类

                抽象类不能用作函数的参数类型 函数的返回类型 或是显式转换的类型

                可以声明指向抽象类的指针或引用 此指针可以指向它的派生类 进而实现多态性

                如果派生类中没有定义纯虚函数的实现 而派生类中只是继承基类的纯虚函数 则这个派生类仍然是一个抽象类 反之则是可以建立对象的具体类

        }

#include <iostream>
using namespace std;

class Figure{
    protected:
        double zozoX, zozoY;
    public:
        Figure(double x, double y) : zozoX(x), zozoY(y) {}
        virtual void getArea() // 基类Figure的虚函数
        {
            cout << "no area for this class" << endl;
        }
};

class Triangle: public Figure{
    public:
        Triangle(double x, double y) : Figure(x, y) {}
        void getArea()  // 重写基类Figure的虚函数
        {
            cout << "area of triangle is: " << 0.5 * zozoX * zozoY << endl;
        }
};

class Square: public Figure{
    public:
        Square(double x, double y) : Figure(x, y) {}
        void getArea()  // 重写基类Figure的虚函数
        {
            cout << "area of square is: " << zozoX * zozoY << endl;
        }
};

class Circle: public Figure{
    public:
        Circle(double x, double y) : Figure(x, y) {}
        void getArea()  // 重写基类Figure的虚函数
        {
            cout << "area of circle is: " << 3.14 * zozoX * zozoX << endl;
        }
};

int main()
{
    Figure *f;
    Triangle t(3, 4);
    Square s(5, 5);
    Circle c(6, 6);

    f = &t;
    f->getArea();
    f = &s;
    f->getArea();
    f = &c;
    f->getArea();

    return 0;
}

   }

  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值