当前位置 博文首页 > nameofcsdn的博客:面向对象程序设计(5)成员默认值、default、

    nameofcsdn的博客:面向对象程序设计(5)成员默认值、default、

    作者:[db:作者] 时间:2021-06-26 09:15

    ?

    目录

    1,成员默认值

    2,default

    3,delete

    4,多继承

    5,虚继承、虚基类


    1,成员默认值

    创建对象时,首先根据成员默认值进行赋值,然后再调用构造函数。

    class A
    {
        int x = 3, y;
    public:
        void out()
        {
            cout << x << "  " << y;
        }
    };
    
    int main()
    {
        A a;
        a.out();
        return 0;
    }

    输出:3 ?-858993460

    默认构造函数什么都不做,不会把未初始化的变量设为0

    class A
    {
        int x = 3, y;
    public:
        A()
        {
            x=2, y = 4;
        }
        void out()
        {
            cout << x << "  " << y;
        }
    };
    
    int main()
    {
        A a;
        a.out();
        return 0;
    }

    输出:2 ?4

    构造函数中重新对x进行了赋值。

    2,default

    #include <iostream>
    using namespace std;
    
    class MyClass
    {
    public:
        int x=2,y=3;
        MyClass()=default;
        MyClass(int x,int y)
        {
            this->x=x,this->y=y;
        }
        void out()
        {
            cout<<x<<" "<<y<<endl;
        }
    };
    
    int main() {
        MyClass cs;
        MyClass cs2(3,4);
        cs.out();
        cs2.out();
        return 0;
    }
    

    default把构造函数设为默认构造函数,不需要函数体,即这个函数什么都不做。

    3,delete

    delete限定函数不可用

    #include <iostream>
    using namespace std;
    
    class MyClass
    {
    public:
        MyClass()=delete;
        ~MyClass()=delete;
        static int* get()
        {
            static int x;
            return &x;
        }
    };
    
    int main() {
        int *p = MyClass::get();
        *p=123;
        int *pp=MyClass::get();
        cout<<*pp;
        return 0;
    }
    

    默认构造函数设为delete之后,就不能调用默认构造函数了。

    加了delete不代表这个函数不存在,只是不能用而已:

    #include <iostream>
    using namespace std;
    
    class MyClass
    {
    public:
        int x=5,y;
        MyClass(int x)=delete;
    };
    
    int main() {
        // MyClass cs;
        return 0;
    }
    

    这里自定义构造函数加了delete之后,默认构造函数也没了

    4,多继承

    (1)多继承

    #include <iostream>
    using namespace std;
    
    class X1
    {
    public:
        int f()
        {
            return 1;
        }
    };
    class X2
    {
    public:
        virtual int f()
        {
            return 2;
        }
    };
    
    class A:X1,X2
    {
    public:
        int f()
        {
            return 3;
        }
    };
    
    class B:public A
    {
    public:
        int f() override
        {
            return 4;
        }
    };
    
    int main() {
        A a;
        A* p = &a;
        if(((X1*)p)->f()==a.f())cout<<"same ";
        else cout<<"not same ";
        if(((X2*)p)->f()==a.f())cout<<"same ";
        else cout<<"not same ";
        return 0;
    }
    

    输出:same, virtual function

    多继承的子类,如果有和父类相同签名的函数,只要各父类有一个是虚函数,子类中就是虚函数。

    如上代码中,X1和A中的f是覆盖hide,非多态,X2和A中的f是重写override,多态。

    A中的f仍然可以用override修饰,这个时候它作为语法糖的作用就是,当且仅当若干个父类中至少有一个是虚函数的时候,编译通过。

    (2)多继承的可见性

    查了网上很多资料,基本都是一致的,多继承也区分共有继承、私有继承等。

    不过我在本地clion实测,以及用力扣c++实测,结果显示就算写的是private继承结果也是共有继承。

    (3)钻石问题

    有多继承就会出现环,这就是钻石问题

    其实最小的环是三角形,不过三角形纯属没必要,而钻石问题的场景,却是实实在在存在的,子类继承2个父类,2个父类都继承了祖父类

    为了避免子类类实例化时两次调用祖父类的构造函数,析构时两次调用祖父类析构函数,可以把祖父类的构造函数和析构函数设为虚函数。

    5,虚继承、虚基类

    把祖父类的构造函数和析构函数设为虚函数,可以解决构造函数和析构函数在子类中有二重身的问题,

    但对于普通成员,还是存在这个问题,解决方法是虚继承,让2个父类都虚继承祖父类,这个场景下的祖父类就叫虚基类。

    ?

    下一篇:没有了