zoukankan      html  css  js  c++  java
  • C++ primer(十三)--类继承、构造函数成员初始化、虚函数、抽象基类

    一、基类

        从一个类派生出另一个类时,原始类称为基类,继承类称为派生类。

    派生类对自身基类的private成员没有访问权限,对基类对象的protected成员没有访问权限,对派生类对象的(基类之外)的private和protected成员具有访问权限。

    由于C++基础不好,平时也不用它,导致今天才纠正一个非常关键的错误,类的访问权限,是对类而言的,而不是对类的对象而言的。一直都理解错了。这句话都没脸写出来,还是写下来了。

    下面是一段简答的测试代码。对于调用成员函数的对象test,基类形参,派生类形参三者的访问权限做了测试如下:

        #include <iostream>  
        using namespace std;  
          
        class base  
        {  
                public:  
                        int pub;  
                protected:  
                        int pro;  
                private:  
                        int pri;  
        };  
          
        class derive : public base  
        {  
                public:  
                        int newpub;  
                protected:  
                        int newpro;  
                private:  
                        int newpri;  
          
                public:  
                        int func(class base a, class derive b)  
                        {  
                        //////////////////////////////////////////  
                        自身的 基类成员和非基类成员访问权限测试  
                                cout << newpub << endl;  
                                cout << newpro << endl;  
                                cout << newpri << endl;  
                                cout << pub << endl;  
                                cout << pro << endl;  
                // no access    cout << pri << endl;  
                  
                        /////////////////////////////////////////  
                        对基类对象访问权限的测试  
                                cout << a.pub << endl;  
                // no access    cout << a.pro << endl;  
                // no access    cout << a.pri << endl;  
                  
                        /////////////////////////////////////////  
                        对派生类对象的基类以及非基类成员访问权限测试  
                                cout << b.pub << endl;  
                                cout << b.pro << endl;  
                //no access     cout << b.pri << endl;  
                                cout << b.newpub << endl;  
                                cout << b.newpro << endl;  
                                cout << b.newpri << endl;                                                                       
                        ////////////////////////////////////////  
          
                                return 0;  
                        }  
        };  
          
        int main()  
        {  
                class base a;  
                class derive b;  
                class derive test;  
                test.func(a, b);  
                return 0;  
        }  

     

    对基类进行继承时,三种继承方式下,基类的三种访问权限在子类中会有如何的变化这个问题,本科时上C++这门课的时候曾仔细的分析并弄得挺清楚,后来时间久了、用的也不多,慢慢的又变得心里不太有谱了。这次接着准备面试的契机,又重新仔细分析了一番,留个案底,以免再犯糊涂。

    三种访问权限

        public:可以被任意实体访问
        protected:只允许子类及本类的成员函数访问
        private:只允许本类的成员函数访问

    三种继承方式

        public 继承  
        protect 继承
        private 继承

    组合结果

        基类中      继承方式             子类中

        public     & public继承        => public
        public     & protected继承     => protected  
        public     & private继承      
    => private

        protected  & public继承        => protected
        protected  & protected继承     => protected  
        protected  & private继承       => private

        private    & public继承        => 子类无权访问
        private    & protected继承     => 子类无权访问
        private    & private继承       => 子类无权访问

    由以上组合结果可以看出

        1、public继承不改变基类成员的访问权限
        2、private继承使得基类所有成员在子类中的访问权限变为private
        3、protected继承将基类中public成员变为子类的protected成员,其它成员的访问       权限不变。
        4、基类中的private成员不受继承方式的影响,子类永远无权访问。

        此外,在使用private继承时,还存在另外一种机制:准许访问。

        我们已经知道,在基类以private方式被继承时,其public和protected成员在子类中变为private成员。然而某些情况下,需要在子类中将一个或多个继承的成员恢复其在基类中的访问权限。

        C++支持以两种方式实现该目的

        方法一,使用using 语句,这是C++标准建议使用的方式
        方法二,使用访问声明,形式为 base-class::member;,位置在子类中适当的访问声明处。(注,只能恢复原有访问权限,而不能提高或降低访问权限)

       
    以下是简单的试验代码
     

    #include <iostream>
    
    using namespace std;
    
    class Grand
    {
    public:
        void public_foo (){}
    protected:
        void protected_foo(){}
    private:
        void private_foo(){}
    };
    
    class Father:public Grand
    {
    public:
        void f_public_test()        {public_foo();    }   
        void f_protected_test()        {protected_foo(); }    
    //    void f_private_test()        {private_foo();   }    
    };
    
    class Child:public Father
    {
    public:
        void c_protected_test()        {protected_foo();  }
    //    void c_private_test()        {private_foo();}
    };
    
    
    int main( int argc, char* argv[])
    {
        Father  objF;
    
    //    objF.protected_foo();
    
        return 1;
    
    }
    
       
       
    
    //protected.cpp
    
    #include <iostream>
    
    using namespace std;
    
    class Grand
    {
    public:
        void public_foo (){}
    protected:
        void protected_foo(){}
    private:
        void private_foo(){}
    };
    
    class Father:protected Grand
    {
    public:
        void f_public_test()        {public_foo();    }   
        void f_protected_test()        {protected_foo(); }    
    //    void f_private_test()        {private_foo();   }    
    };
    
    class Child:public Father
    {
    public:
        void c_protected_test()        {protected_foo();  }
    //  void c_private_test()        {private_foo();}
    };
    
    
    int main( int argc, char* argv[])
    {
        Father  objF;
    
    
    //    objF.public_foo();
    //    objF.protected_foo();
    
        return 1;
    
    }
    
    
    //private.cpp
    
    #include <iostream>
    
    using namespace std;
    
    class Grand
    {
    public:
        void public_foo (){}
    protected:
        void protected_foo(){}
    private:
        void private_foo(){}
    };
    
    class Father:private Grand
    {
    public:
        void f_public_test()        {public_foo();    }   
        void f_protected_test()        {protected_foo(); }    
    //    void f_private_test()        {private_foo();   }    
    };
    
    class Child:public Father
    {
    public:
    //    void c_protected_test()        {protected_foo();  }
    //    void c_private_test()        {private_foo();}
    };
    
    
    int main( int argc, char* argv[])
    {
        Father  objF;
    
    //    objF.public_foo();
    //    objF.protected_foo();
    
        return 1;
    
    }



  • 相关阅读:
    6.8
    6.7
    6.2
    6.1儿童节
    5.24
    5.22
    5.18
    5.17
    Visual Studio开始一个HelloWorld的enclave程序
    以太坊MPT树的HP(Hex-Prefix)编码
  • 原文地址:https://www.cnblogs.com/fuhaots2009/p/3360769.html
Copyright © 2011-2022 走看看