精华内容
下载资源
问答
  • C++继承关系

    千次阅读 2016-11-08 12:50:15
    C++继承关系 一、继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象...

                            C++中的继承关系

    一、继承概念

    继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能。这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。

    简单的说,如果用继承关系来描述手机的发展的话,就如下图所示的关系:


        上图描述的是某手机的ABC三个版本,后一个版本总是在保持原有版本功能的情况下增加了自己新的功能。

    下面我们来说说继承在C++中的作用:

    通过继承联系在一起的类构成一种层次关系,通常在层次关系的根部有一个基类,其他类则直接或间接地从基类继承而来,这些继承得到的类成为派生类,基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。注意,基类通常都应该定义一个虚析构函数,即使该函数不执行任何实际操作也是如此。

    二、继承的定义格式

    class  DeriveClassName : acess-lable  BaseClassName

            派生类类名    继承权限    基类(父类)名

    继承权限:指三种继承关系,public(公有继承)、protected(保护继承)、    private(私有继承)。

    三、继承关系

    在继承中,根据继承权限的不同,基类成员的访问权限会在派生类中发生适当的改变,下面我们对三种不同访问权限对基类成员在派生类中的访问权限的影响。

    继承权限为public时:

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    Base()

    {

    cout << "Base()" << endl;

    }

    virtual ~Base()

    {

    cout << "~Base()" << endl;

    }

    void showBase()

    {

    cout << "_pub=" << _pub << endl;

    }

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    Derive()

    {

    cout << "Derive()" << endl;

    }

    void showDerive()

    {

    cout << "_D_pub=" << _D_pub << endl;

    }

    virtual ~Derive()

    {

    cout << "~Derive()" << endl;

    }

    void FunTest1()

    {

    Derive d1;

    d1._pro = 10;   //可以访问

    d1._pub = 11;   //可以访问

    d1._pri = 12      //不能访问

    }

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void FunTest2()

    {

    Derive d1;

    d1._pro = 10;   //不能访问

    d1._pub = 11;   //可以访问

    d1._pri = 12;   //不能访问

    }

    分析

      这了给出了一个基类Base类和一个派生类Dierived类,我们来简单分析一下这两个类


    这个函数是上面派生类中的一个测试函数,我们可以看到,在派生类中,基类的公有成员和保护成员可以访问,但私有成员是不能被访问的。

     

    FunTest2函数是类外的一个测试函数,可以看到,在类外通过创建的派生类对象可以对基类中的公有成员进行访问,但保护成员和私有成员都不能被访问。

    继承权限为protected时:

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    Base()

    {

    cout << "Base()" << endl;

    }

    virtual ~Base()

    {

    cout << "~Base()" << endl;

    }

    void showBase()

    {

    cout << "_pub=" << _pub << endl;

    }

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :protected Base

    {

    public:

    Derive()

    {

    cout << "Derive()" << endl;

    }

    void showDerive()

    {

    cout << "_D_pub=" << _D_pub << endl;

    }

    virtual ~Derive()

    {

    cout << "~Derive()" << endl;

    }

    void FunTest1()

    {

    Derive d1;

    d1._pro = 10;   //可以访问

    d1._pub = 11;   //可以访问

    d1._pri = 12;     //不能访问

    }

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    class D :public Derive

    {

    public:

    D()

    {}

    virtual ~D()

    {}

    void FunTest3()

    {

    D d;

    d._pro = 10;   //可以访问

    d._pub = 11;   //可以访问

    d._pri = 12;     //不能访问

    }

    private:

    int data;

    };

    分析:

        

        从截图中我们可以看见,派生类中的FunTest1函数中创建的对象可以对基类中的公有和保护成员变量进行访问,但不能对私有成员变量进行访问。

     

    FunTest3是派生类D中的一个函数,D是Deriver的一个派生类,可以看出,在D中,对象对基类Base中的公有、保护类型成员可以访问,而私有成员不能访问。

     

    在类外的测试函数FunTest2中,Base基类中的所有成员都不能被D类的对象进行访问。

    由此可以看出,Base基类中的成员变量在Derive继承下来后都把公有访问权限改成保护类型。

    继承权限为private时:

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    Base()

    {

    cout << "Base()" << endl;

    }

    virtual ~Base()

    {

    cout << "~Base()" << endl;

    }

    void showBase()

    {

    cout << "_pub=" << _pub << endl;

    }

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :private Base

    {

    public:

    Derive()

    {

    cout << "Derive()" << endl;

    }

    void showDerive()

    {

    cout << "_D_pub=" << _D_pub << endl;

    }

    virtual ~Derive()

    {

    cout << "~Derive()" << endl;

    }

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    class D :public Derive

    {

    public:

    D()

    {}

    virtual ~D()

    {}

    void FunTest3()

    {

    D d;

    d._pro = 10;   //不能访问

    d._pub = 11;   //不能访问

    d._pri = 12;     //不能访问

    }

    private:

    int data;

    };

    void FunTest2()

    {

    Derive d1;

    d1._pro = 10;   //不能访问

    d1._pub = 11;   //不能访问

    d1._pri = 12;   //不能访问

    }

    分析:

     

    FunTest3是派生类D中的一个函数,D是Deriver的一个派生类,可以看出,在D中,对象对基类Base中的公有、保护和私有类型也都不可以访问。由此可以看出,Base基类中的成员变量在Derive继承下来后都把访问权限改成了私有;类型。

    总结:

    通过对三种继承权限不同情况的分析,我们可以得出下列结论:


    1. 基类的 private成员在派生类中是不能被访问的,如果基类成员不想在类外直                接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。

    2. public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象也都是一个父类对象。

    3. protetced/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是has-a的关系原则,所以非特殊情况下不会使用这两种继承关系,在绝大多数的场景下使用的都是公有继承。私有继承以为这is-implemented-in-terms-of(是根据……实现的)。通常比组合(composition)更低级,但当一个派生类需要访问基类保护成员或需要重定义基类的虚函数时它就是合理的。

    4. 不管是哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见(不能访问)。

    5. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式。

    6. 在实际运用中一般使用都是public继承,极少场景下才会使用protetced/private继承.

    四、派生类的默认成员函数

    类的六个默认的成员函数,他们分别是构造函数、拷贝构造函数、析构函数、赋值操作符重载、取地址操作符重载、const修饰的取地址操作符重载。

    在继承关系里面,在派生类中如果没有显示定义这六个默认构造函数,编译器系统会默认合成这六个成员函数。

     

    继承关系中构造函数的调用顺序

    首先我们先来看一段代码,看看编译器的运行结果:

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    Base()

    {

    cout << "Base()" << endl;

    }

    ~Base()

    {

    cout << "~Base()" << endl;

    }

    void showBase()

    {

    cout << "_pub=" << _pub << endl;

    }

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    Derive()

    {

    cout << "Derive()" << endl;

    }

    void showDerive()

    {

    cout << "_D_pub=" << _D_pub << endl;

    }

    ~Derive()

    {

    cout << "~Derive()" << endl;

    }

     

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void FunTest()

    {

    Derive d;

    d._pub = 10;

    }

    int main()

    {

    FunTest();

    system("pause");

    return 0;

    }

    运行结果:

     

    从运行结果看,是先调用基类的构造函数,然后调用派生类的构造函数,再调用派生类的析构函数,最后调用基类的析构函数。可实际上编译器是不是按照这个顺序呢?我们来看看此程序的汇编代码一查究竟。

     

     

     

     

        从截图中可以看出来,在地址为37D0处调用了Derive的构造函数,而在地址在3815处才调用了Base类的构造函数,具体的大家也可以把程序复制到自己的编译器上调试一步一步跟一下。

    所以说编译器实际上是先调用派生类的构造函数的,但编译器是在什么时候调用的呢?其实编译器是先进入派生类的构造函,然后在初始化列表处调用了基类的构造函数,然后再回来执行自己的函数体。构造函数说清楚了,析构函数的调用顺序似乎还是很模糊,编译器为什么会先调用派生类的析构函数呢?这个编译器是根据生命周期的长短来调用的,派生类中构造函数生命周期比基类的生命周期短,所以就先调用派生类的析构函数。

    【说明】

    1、基类没有缺省构造函数,派生类必须要在初始化列表中显式给出基类名和参数列表。

    2、基类没有定义构造函数,则派生类也可以不用定义,全部使用缺省构造函数。

    3、基类定义了带有形参表构造函数,派生类就一定定义构造函数。

    五、继承体系中的作用域

    1. 在继承体系中基类和派生类是两个不同作用域。

    2. 子类和父类中有同名成员,子类成员将屏蔽父类对成员的直接访问。(在子类成员函数中,可以使用 基类::基类成员 访问)--隐藏--重定义

          验证:

       class Base

    {

    public:

    int _Data;

    };

    class Derive :public Base

    {

    public:

    int _Data;

    };

    void FunTest()

    {

    Derive d;

    d._Data = 10;

    }

    int main()

    {

    FunTest();

    system("pause");

    return 0;

    }

         

        从截图中看出,只改变了派生类中成员的值,这就是由于基类和派生类中使用了同名的成员变量,而派生类中的成员变量对基类中的同名成员变量形成了覆盖/重定义。

    3. 注意在实际中在继承体系里面最好不要定义同名的成员。

    六、继承与转换--赋值兼容规则--public继承

    1. 子类对象可以赋值给父类对象(切割/切片)。

    2. 父类对象不能赋值给子类对象。

          验证1,2

         #include<iostream>

    using namespace std;

    class Base

    {

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void FunTest()

    {

    Base b;

    Derive d;

    b = d;    //能赋值

    d = b;    //不能赋值

    }

    int main()

    {

    FunTest();

    system("pause");

    return 0;

    }

     

        我们可以看到,编译器会在第二次赋值报错,这说明子类对象可以赋值给父类对象,而父类对象不能赋值给子类对象。其实这里面的原因很简单,我们前面说过,public继承是保持is-a的原则,每个子类对象也是一个父类对象,但由于子类对象添加了新的功能,所以,一个父类对象并不是一个子类对象,所以父类对象不能给子类对象赋值。

    3. 父类的指针/引用可以指向子类对象

    4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)

    下面我们用一段代码来证明:

       验证3,4

    在这里我首先提示一下,34的验证尽量不要放在同一段代码中,我看的一些文章中把这四个放在一块证明,不小心的话会遇到一些不必要的麻烦,因为前两个的赋值如果没屏蔽的话会对后面两个造成影响。

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void FunTest()

    {

    Base b;

    Derive d;

    Base* pb1 = &b;

    pb1 = &d;

    Derive* d1 = &d;

    d1 = &b;     

    d1 = (Derive*)&b;

    }

    int main()

    {

    FunTest();

    system("pause");

    return 0;

    }

     

    我们可以看到,父类的指针可以指向子类的对象,而子类的对象不可以指向父类的对象,编译器会报错,但最后一句中,我们可以通过强制类型转换的方式实现,但建议大家尽量别使用,因为那种方式可能造成程序崩溃,而这种错误是很难找出来的。

    七、友元于继承

    友元关系不能继承,也就是说基类友元不能访问子类的私有和保护成员。

       验证:

      #include<iostream>

    using namespace std;

    class Base

    {

    friend void show(Base &b,Derive d);

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void show(Base b,Derive d)

    {

    cout << b._pub << endl;

    cout << b._pro << endl;   //无法访问protected成员,因为友元关系未继承

    cout << d._D_pub << endl;

    }

    void FunTest1()

    {

    Base b;

    Derive d;

    show(b, d);

    }

    int main()

    {

    FunTest1();

    system("pause");

    return 0;

    }

     

         正如截图中显示的那样,对于基类的保护类成员是无法访问的,原因就是友元关系未继承。但是下面这种情况就要注意了,输出运算符的重载,这个例子并不能说明友元被继承了。这个是因为参数发生类型转换,派生类对象赋值给基类对象。

    #include<iostream>

    using namespace std;

    class Base

    {

    friend ostream& operator<<(ostream& _cout,Base& b)

    {

    _cout << b._pri << endl;

    return _cout;

    }

    public:

    int _pub;

    protected:

    int _pro;

    private:

    int _pri;

    };

    class Derive :public Base

    {

    public:

    int _D_pub;

    protected:

    int _D_pro;

    private:

    int _D_pri;

    };

    void FunTest1()

    {

    Base b;

    Derive d;

    cout << b << endl;

    cout << d << endl;

    }

    int main()

    {

    FunTest1();

    system("pause");

    return 0;

    }

    八、继承与静态成员

    如果基类定义了static成员,则整个继承体系里面只有一个这样的成员,无论派生出多少个子类,都只有一个static成员实例。

    九、单继承&多继承&菱形继承

      

        单继承:一个子类只有一个直接父类时称为单继承

         

     

         多继承:一个子类有两个或者两个以上父类的继承关系称为多继承

     


     

    菱形继承:

     


    菱形继承的对象模型:

     

      从对象模型中我们可以发现,菱形继承具有二义性和数据冗余的问题,图中显示Base被存了两份,那么要解决这个问题,C++中引入了我们下面要讨论的一种继承方式——虚继承。

    十、虚继承

        1. 虚继承解决了在菱形继承体系里面子类对象包含多份父类对象的数据冗余&浪费空间的问题。

    2. 虚继承体系看起来好复杂,在实际应用我们通常不会定义如此复杂的继承体系。一般不到万不得已都不要定义菱形结构的虚继承体系结构,因为使用虚继承解决数据冗余问题也带来了性能上的损耗。

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    int data1;

    };

    class Derive :virtual public Base

    {

    public:

    int data2;

    };

    class E :virtual public Base

    {

    public:

    int data4;

    };

    class F :public Derive,public E

    {

    public:

    int data5;

    };

     

    void FunTest1()

    {

    cout << sizeof(Derive) << endl;

    }

    int main()

    {

    FunTest1();

    system("pause");

    return 0;

    }

     

    上述代码计算的是Derive类的大小,结果是12,我们不禁就会想,大小=自己的成员变量大小+基类成员变量大小,为什么会多出来个四呢?其实是多存放了一个指针。而这个指针是干什么用的呢?我们通过代码验证一下:

    #include<iostream>

    using namespace std;

    class Base

    {

    public:

    int data1;

    };

    class Derive :virtual public  Base

    {

    public:

    int data2;

    };

    class E :virtual public  Base

    {

    public:

    int data3;

    };

    class F :public  Derive,public E

    {

    public:

    int data4;

    };

    void FunTest()

    {

     

    F f;

    f.data1 = 1;

    f.data2 = 2;

    f.data3 = 3;

    f.data4 = 4;

    }

    int main()

    {

     

    FunTest();

    system("pause");

    return 0;

    }

     

    上图为我们取到的对象f的地址,从内存可以看出第一个存了一个指针,下面才是赋值,那我们再看一下这个指针指向了哪:

     

     

     

    我们看到里面有个0,有个20,这正好是到Base类的偏移量,所以,这个表中存的是此类到基类的偏移量,而不用把Base类存两遍。解决了冗余问题。

     

       从内存中f各个变量的存储我们不难看出虚拟继承的模型图,如下图所示:

     

     

    展开全文
  • fork之后进程的数据和文件描述符的继承 2013-12-08 00:00:50 分类: C/C++ 1.fork()、文件和数据 用系统 fork() 建立的子进程几乎与其父进程完全一样。子进程的所有变量均保持它们在父进程...
    
    

    分类: C/C++

    1.fork()、文件和数据
    用系统 fork() 建立的子进程几乎与其父进程完全一样。子进程中的所有变量均保持它们在父进程中之值(fork()的返回值除外) 。因为子进程可用的数据是父进程可用数据的拷贝,并且其占用不同的内存地址空间,所以必须要确保以后一个进程中变量数据的变化,不能影响到其它进程中的变量。这一点非常重要。另外,在父进程中已打开的文件,在子进程中也已被打开,子进程支持这些文件的文件描述符。但是,通过 fork()调用后,被打开的文件与父进程和子进程存在着密切的联系,这是因为子进程与父进程公用这些文件的文件指针。这就有可能发生下列情况:由于文件指针由系统保存,所以程序中没有保存它的值,从而当子进程移动文件指时也等于移动了父进程的文件指针。这就可能会产生意想不到到结果。为了说明上述情况,我们给出一个实例程序 proc_file。在这个程序中使用了两个预定义的函数 failure()和 printpos()。failure()用来完成简单的出错处理,它只是调用 perror() 来显示出错信息。其实现如下:
    failure( char* s)
    {
        perror(s);
        exit(1);
    }
    printpos()实现显示一个文件的文件指针之值,其实现如下:
    printpos( char* string, int  fildes)
    {
        long  pos;
        if ((pos=lseek(fildes,0L,1)<0L)
            failure( “ lseek failed” );
        printf(“ %s: %ld \n” ,string,pos);
    }
    另外我们还假定文件 data 已经存在,并且它的长度不小于 20 个字符。下面给出程序proc_file 的清单:

    #include 
    #include 
    #include 
    failure( char* s)
    {
        perror(s);
        exit(1);
    }
    printpos( char* string, int  fildes)
    {
        long  pos;
        if ((pos=lseek(fildes,0L,1))<0L)
            failure("lseek failed");
        printf("%s: %ld \n",string,pos);
    }
    main()
    {
        int  fd; /*  文件描述符*/
        int  pid;/*  进程标识符*/
        char buf[10]; /*  数据缓冲区*/
        /*  打开文件*/
        if ((fd=open(" data",O_RDONLY))<0)
            failure("open failed");
        read(fd,buf,10); /* advance file pointer */
        printpos("Before fork",fd);
        /* fork 新进程*/
        if ((pid=fork())<0)
            failure("fork failed");
        else if (!pid)
            /*  子进程*/
            printpos("Child before  read",fd);
            read(fd,buf,10);
            printpos("child after read",fd);
        } else {
            /*  父进程*/
            /*  等待子进程运行结束*/
            wait(NULL);
            printpos("parent after wait",fd);
        }
    }
    该程序运行结果如下:
    Child before read: 10
    child after read: 20
    parent after wait: 20
    这充分证明了文件指针为两个进程共用这一事实。
    2.exec()和打开文件
    当一个程序调用 exec 执行新程序时,在程序中已被打开的文件,其在新程序中仍保持打开。这就是说,已打开文件描述符能通过 exec 被传送给新程序,并且这些文件的指针也不会被 exec 调用改变。这儿,我们要介绍一个与文件有关的执行关闭位(close-on-exec ) ,该位被设置的话,则调用 exec 时会关闭相应的文件。该位的默认值为非设置。例行程序 fcntl 能用于对这一标志位的操作,下面的程序段给出了设置“执行关闭”位的方法。
    #include 



    int  fd;
    fd=open(“ file ” ,O_RDONLY);


    fcntl(fd,F_SETFD,1);
    如果已经设置了执行关闭位,我们可以用下面的语句来撤销“执行关闭“位的设置,并取得它的返回值:
    res =fcntl(fd,F_SETFD,0);
    如果文件描述符所对应的文件的“执行关闭位”已经被设置,则 res 为 1,否则 res 之值为 0。
    展开全文
  • 关于继承的说法正确的是

    千次阅读 2019-02-26 13:17:00
    关于继承的说法正确的是(A)。 子类将继承父类所有的数据域和方法。 子类将继承父类的其可见的数据域和方法。 子类只继承父类public方法和数据域 子类只继承父类的方法,而不继承数据...

    关于继承的说法正确的是(A)。

    • 子类将继承父类所有的数据域和方法。
    • 子类将继承父类的其可见的数据域和方法。
    • 子类只继承父类public方法和数据域
    • 子类只继承父类的方法,而不继承数据域

    在一个子类被创建的时候,

    • 首先会在内存中创建一个父类对象,
      • 然后在父类对象外部放上子类独有的属性,
      • 两者合起来形成一个子类的对象。
    • 所以所谓的继承使子类拥有父类所有的属性和方法其实可以这样理解,
      • 子类对象确实拥有父类对象中所有的属性和方法,
      • 但是父类对象中的私有属性和方法,子类是无法访问到的,
        • 只是拥有,但不能使用。
    • 就像有些东西你可能拥有,但是你并不能使用。
      • 所以子类对象是绝对大于父类对象的,
      • 所谓的子类对象只能继承父类非私有的属性及方法的说法是错误的。
      • 可以继承,只是无法访问到而已。

    转载于:https://my.oschina.net/u/3847203/blog/3014926

    展开全文
  • 以下关于java封装的描述中,正确的是: 正确答案:A 你的答案:A(正确) 封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性 封装的意义不大,因此在编码中尽量不要使用 如果子类继承父类,对于...
    以下关于java封装的描述中,正确的是:

    正确答案:A  你的答案:A(正确)

    封装的主要作用在于对外隐藏内部实现细节,增强程序的安全性
    封装的意义不大,因此在编码中尽量不要使用
    如果子类继承父类,对于父类中进行封装的方法,子类仍然可以直接调用
    只能对一个类中的方法进行封装,不能对属性进行封装
    展开全文
  • 许多 OO语言都支持两种继承方式:接口继承和实现继承。 接口继承继承方法签名,而实现继承继承实际的方法。 如前所述,由于函数没有签名,在 ECMAScript无法实现接口继承。ECMAScript只支持实现继承,而且其...
  • 关于类的组合和继承

    千次阅读 2015-08-22 22:15:12
    【出处】... ... 在我们对现实的某些事物抽象成类时,可能会形成很复杂的类,为了更简洁的进行软件开发,我们经常把其中相对比较独立的部分拿出来定义成一个个简单的类,这些比较简单的类又可
  • C#继承与多态

    万次阅读 2011-04-06 18:38:00
    一、继承的基础知识  为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在 自己的开发过程能够有足够的灵活性,不拘泥...
  • 在JAVA,下面对继承的说法,正确的是() A. 子类能继承父类的所有成员 B. 子类继承父类的非私有方法和状态 C. 子类只能继承父类的public方法和状态 D. 子类只能继承父类的方法 答案:A 解析: 我们有时候会分不清...
  • 关于类的序列化,下列说法哪些是正确的:答案在文末 A. 类的序列化与serialVersionUID毫无关系。 B. 如果完全不兼容升级,不需要修改serialVersionUID值。 C. POJO类的serialVersionUID不一致会编译出错。 D. POJO...
  • 继承 选择题 大一期末复习

    千次阅读 2018-07-04 17:18:09
    在C++中,类之间的继承...在下列关于类的继承描述中,正确的是(D )。(A)派生类公有继承基类时,可以访问基类的所有数据成员,调用所有成员函数(B)派生类也是基类,所以它们是等价的(C)派生类对象不会建立基...
  • 什么面向对象?一句话,万物皆对象。 比如,人是一个类,男人或女人就是人类的...封装、继承、多态。 首先,我们先通过一个有趣的比喻说明来理解。  首先说定义一类人被封装成“贪官”,我们就是平民老
  • Java继承练习题

    千次阅读 2020-05-11 20:18:34
    2.在Java,以下关于方法重载和方法重写描述正确的是 A A. 方法重载和方法重写实现的功能相同 B. 方法重载出现在父子关系,方法重写是在同一类 C. 方法重载的返回类型必须一致,参数项必须不同 D. 方法重写需要...
  • Java继承多态部分习题

    万次阅读 2018-07-06 18:22:44
    1 下列程序的输出结果为:class Base { Base() { int i = 100; System.out.println(i); } } public class Pri extends Base { static int i = 200; public static void main(String argv[]) ...
  • 继承作业及答案

    千次阅读 2019-04-24 13:11:34
    以下关于继承条件下构造方法执行过程的代码的执行结果是( )。(选择一项) class Person { public Person() { System.out.println(“execute Person()”); } } class Student extends Person { public Student()...
  • 继承多态习题

    万次阅读 2017-04-13 21:51:44
    4.4 精选习题 ...1.下列程序运行结果是( )。 private class Base {  Base() {  int i = 100;  System.out.println(i);  } } public class Pri extends Base {  static int i = 200;  
  • C#继承详解

    千次阅读 2008-11-07 16:26:00
    继承基础知识 为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程能够有足够的灵活性,不拘泥于复用的模块。...
  • 1、继承(is-a)  指的是一个类(称为子类、...在Java此类关系通过关键字extends明确标识,在设计时一般没有争议性;   2、实现  指的是一个class类实现interface接口(可以是多个)的功能;实现是类与接口之
  • 子进程继承父进程用户号UIDs和用户组号GIDs ...文件方式创建屏蔽字 资源限制 控制终端子进程独有 进程号PID 不同的父进程号 自己的文件描述符和目录流的拷贝 子进程不继承父进程的进程正文(text
  • 1、为啥继承时基类的析构函数声明为虚函数? 文字描述太抽象了,直接用代码给出答案。 (1)第一段代码: #include using namespace std ; class Base { public: Base() { cout 基类的构造函数被调用了" ...
  • C/C++ 类的继承与派生

    千次阅读 2019-05-25 19:47:15
    before|正文之前: c++实验代码及学习笔记(九) 你好! 这是一个高程实验课的代码记录及学习笔记。我将记录一些重要的知识点、易错点。但是作为大学生,水平很低,敬请指点教导、优化代码。...C++的继...
  • 继承、封装和多态是面向程序设计(OOP)的三大特点,而它们三者之最具实际操作性的当属继承。通过继承可以实现简单功能的组合和定制,而多重继承更将这种能力发挥到更高的境界。不过事事都有弊端,如果使用多重继承...
  • PTA 继承第一次实验(选择题解析)

    千次阅读 2019-06-04 14:29:39
    继承第一次实验 2-1 一个类的私有成员 (2分) 只能被该类的成员函数访问 ...以下关于C++语言中继承的叙述,错误的是( )。 (2分) 继承是父类和子类之间共享数据和方法的机制 继承定义了一种类与类之间的关系...
  • C#的继承机制

    千次阅读 2005-08-29 18:01:00
    继承基础知识 为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程能够有足够的灵活性,不拘泥于复用的模块。...
  • 描述 instance 定义了当前  FileField  的 model 实例。更准确地说,就是以该文件为附件的 model 实例。 大多数情况下,在保存该文件时, model 实例对象还并没有保存到数据库,这是因为...
  • 本篇文章,我们一起探讨了OpenCV仿射变换和SURF特征点描述相关的知识点,主要一起了解OpenCV仿射变换相关的函数warpAffine和getRotationMatrix2D,SURF算法在OpenCV进一步的体现与应用。此博文一共有两个...
  • Objective-C 的“多继承

    万次阅读 多人点赞 2013-05-24 17:10:43
    Objective-C 的“多继承” 当单继承不够用,很难为问题域建模时,我们通常都会直接想到多继承。多继承是从多余一个直接基类派生类的能力,可以更加直接地为应用程序建模。但是Objective-C不支持多继承,由于消息...
  • C#类的继承机制

    千次阅读 2009-07-31 10:52:00
    个人觉得写的很经典的一篇文章,关于C#类的继承机制。 转过来 供自己学习之用================================================================一. 继承基础知识 为了提高软件模块的可复用性和可扩充性,以便提高...
  • 深入剖析C#继承机制

    千次阅读 2005-07-20 10:20:00
    继承基础知识 为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总是希望能够利用前人或自己以前的开发成果,同时又希望在自己的开发过程能够有足够的灵活性,不拘泥于复用的模块。...
  • 1、下列关于继承描述错误的是( )  A. 在Java允许定义一个父类的引用,指向子类对象  B. 在Java中继承是通过extends关键字来描述的,而且只允许继承自一个直接父类  C. 在Java抽象类之间也允许出现...
  • 类图是使用频率最高的UML图之一,主要用于描述系统所包含的类以及它们之间的相互关系,帮助开发人员理解系统,它是系统分析和设计阶段的重要产物,也是系统编码和测试的重要模型依据。 类间的关系包括关联、继承、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,893
精华内容 18,357
关键字:

下列关于继承方式的描述中