精华内容
下载资源
问答
  • 重写是继承的时候,重写是子类父类允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。 重载,是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。重载可以避免使用完全不同...

    重写和重载

    重写是继承的时候,重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
    重载,是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。重载可以避免使用完全不同的方法来完成几乎相同的任务,可以使方法根据受到的参数的不同,执行不同的操作。

    子类重写父类的方法

    子类重写了父类的方法,如果用父类的对象去调用,就会使用父类的实现
    如果用子类的对象去调用,就会使用子类的实现。
    如果是父类的声明,子类的对象:

    Father father = new Son();
    

    上述father
    (1)在Father类的main函数里面,可以直接访问Father没有被重写的方法
    这是因为子类继承了这些方法,子类可以继承父类允许访问的变量和方法
    (2)在Father类的main函数里面,想访问子类的重写过的方法或者子类独有的方法,必须要强制类型转换。

    (Son)father.SonFunction
    

    (3)在Father类的main函数里面,某方法被子类重写过,但是想调用Father类被重写之前的实现方法,就是指子类的对象要调用父类被重写之前的方法。
    需要在子类的实例方法中,使用super关键字调用父类的方法。
    使用super关键字访问超类:
    只能在子类的构造函数或非静态方法(实例方法)中访问。

    (4)在Son的main函数里面,可以直接访问Son的所有方法,包括重写过的父类方法。
    (5)在Son的main函数里面,如果调用子类独有的办法,需要强制类型转换

    (Son)father.SonFunction
    

    综上,如果是父类声明,子类实例化,想调用子类独有的方法,必须要强制类型转换。

    展开全文
  • 也要包含B.h,但是相互包含是不允许的,称为环形引用,这时候就用到了前向声明 文章目录1,a.h 类A中实例化类B的对象2,a.cpp 可以调用类B对象的方法3,b.h 类B中不能实例化类A的对象4,b.cpp 中包含a.h,这样就...

    假设声明两个类A和B,如果需要在A.h中定义B类对象,B b_; 势必要包含# include “B.h”,而B类中需要定义A类对象A a_; 也要包含B.h,但是相互包含是不允许的,称为环形引用,这时候就用到了前向声明

    1,a.h 类A中实例化类B的对象

    #ifndef __A_H__
    #define __A_H__
    
    #include <iostream>
    #include <stdio.h>
    #include "b.h" //类A中要实例化一个类B的对象
    
    class BasicA {
    protected:
        int m_a = 1;
    public:
        void print_a2() {
            std::cout << "a2:" << m_a << std::endl; 
        };
    };
    
    class A : public BasicA {
    private:
        B m_b;//例化一个类B的对象
    public:
        A();
        ~A();
        void print_a();
        void print_this();
    };
    #endif
    

    2,a.cpp 可以调用类B对象的方法

    A::A() {
        std::cout << "this->p:" << (void *)&m_a << std::endl;
        m_b.set_a(this); //将类A的真实指针传给类B
    }
    A::~A(){
    }
    void A::print_a() {
        m_a = 2;
        std::cout << "a:" << m_a << std::endl; 
        m_b.print_b(); //调用类B对象的方法
    }
    void A::print_this() {
        std::cout << "a this" << std::endl;
    }
    

    3,b.h 类B中不能实例化类A的对象

    #ifndef __B_H__
    #define __B_H__
    #include <iostream>
    
    class A; //类A的前置声明
    
    class B{
    private:
        int m_b = 1;
        A *m_a; //定义一个类A的指针,用作占位
    public:
        B();
        ~B();
        void set_a(A *a); //用于将实际的类A的指针传进来
        void print_b();
    };
    #endif
    

    4,b.cpp 中包含a.h,这样就可以使用类A对象中的方法

    #include "b.h"
    #include "a.h"
    
    B::B(){}
    B::~B(){}
    
    void B::set_a(A *a) {
        m_a = a;
        std::cout << "ma->p:" << (void *)m_a << std::endl;
    }
    
    void B::print_b() {
        std::cout << "b:" << m_b << std::endl; 
    
        m_a->print_this(); //使用类A对象的方法
    }
    

    5,main.cpp

    #include <iostream>
    #include "a.h"
    
    int main() {
        A a;
        a.print_a2();
        a.print_a();
        std::cout << "111111111111111111111111" << std::endl;
    }
    

    6,运行

    在这里插入图片描述

    展开全文
  • 点击上方“程序员大咖”,选择“置顶公众号”关键时刻,第一时间送达!Java 和 C++ 都是面向对象的语言,允许对象之间的继承。两个语言的继承都设置有允许子类覆盖父类的“...
        

    点击上方“程序员大咖”,选择“置顶公众号”

    关键时刻,第一时间送达!640?640?wx_fmt=gif


    Java 和 C++ 都是面向对象的语言,允许对象之间的继承。两个语言的继承都设置有允许子类覆盖父类的“虚函数”,加引号是因为 Java 中没有虚函数这一术语,但是我们的确可以把 Java 的所有函数等同于虚函数,因为 Java 类的所有非 static 函数都可以被子类覆盖,这里仅借用“虚函数”这一名词的含义,不深究语言的术语问题。


    Java 和 C++ 都允许在子类覆盖父类时,改变函数的可访问性。所谓“可访问性”,就是使用 public 、protected、private 等访问控制符进行修饰,用来控制函数能否被访问到。通常可访问性的顺序为(由于 C++ 中没有包的概念,因此暂不考虑包访问控制符,这并不影响这里的讨论):


    public > protected > private


    以 Java 为例:


    class Base {
       protected void sayHello() {
           System.out.println("Hello in Base");
       }
    }
    class Child extends Base {
       public void sayHello() {
           System.out.println("Hello in Child");
       }
    }


    注意这里的 sayHello() 函数,父类 Base 中,该函数使用 protected 访问控制符进行修饰,而子类将其改用 public,这不会有任何问题。子类对父类函数覆盖时,扩大可访问性,通常都不是问题。


    本文要讲的是,当子类对父类函数覆盖的可访问性缩小时,Java 和 C++ 采取了不同的策略。


    首先以 Java 为例,看下面的代码:


    class Base {
       public void sayHello() {
           System.out.println("Hello in Base");
       }
    }
    class Child extends Base {
       private void sayHello() {
           System.out.println("Hello in Child");
       }
    }


    上面的代码中,第 8 行 **private void sayHello() {**会有编译错误,导致这段代码根本不能通过编译。因为 Java 不允许子类在覆盖父类函数时,缩小函数的可访问性,至于原因,我们可以用一个例子来说明。


    例如我们在外部调用时使用下面的代码:


    Base base = new Base();
    base.sayHello();
    base = new Child();
    base.sayHello();


    假如之前的代码可以通过编译,那么就存在这么一种可能:由于 Java 是运行时绑定,当 base 指向 new Base() 时, sayHello() 是可以访问到的,但是当 base 指向 new Child() 时,sayHello() 却无法访问到!在 Java 看来这是一个矛盾,应该避免出现这种问题,因此,Java 从编译器的角度规定我们不能写出上面的代码。


    而在 C++ 中,情况就不同了,来看 C++ 的例子:


    class Base {
    public:
       virtual void sayHello() {
           std::cout << "Hello in Base";
       }
    }
    class Child : public Base {
    private:
       void sayHello() {
           std::cout << "Hello in Child";
       }
    }


    这段代码在 C++ 中是完全正确的,可以通过编译。注意,这里的子类在覆盖父类函数时,缩小了可访问性。如果你没有看出有什么问题,那么我们完全可以在外部调用时使用下面的代码:


    Child child;
    child.sayHello(); // 不能通过编译,因为 sayHello() 是 private 的
    static_cast<Base&>(child).sayHello(); // 可以通过编译,因为 sayHello() 是 public 的


    第 2 行调用是失败的,因为在 Child 中,sayHello() 是 private 的,不能在外部调用。然而,当我们使用 static_cast 运算符将 Child 强制转换成 Base 类型时,事情发生了改变——对于 Base 而言,sayHello() 是 public 的,因此可以正常调用。

    针对这一点,C++ 标准的《Member access control》一章中《Access to virtual functions》一节可以找到如下的例子:


    class B {
    public:
       virtual int f();
    };
    class D : public B {
    private:
       int f();
    };
    void f() {
       D d;
       B* pb = &d;
       D* pd = &d;
       pb->f(); // OK: B::f() is public, D::f() is invoked
       pd->f(); // error: D::f() is private
    }


    对此,C++ 标准给出的解释是:


    Access is checked at the call point using the type of the expression used to denote the object for which the member function is called ( B* in the example above). The access of the member function in the class in which it was defined (D in the example above) is in general not known.


    简单翻译过来有两条要点:


    • 访问控制是在调用时检查的,也就是说,谁调用了这个函数,就检查谁能不能访问这个函数。

    • 成员函数的可访问性一般是不知道的,也就是说,运行时检查可访问性时,并不能知道这个函数在定义时到底是 public 的还是 private 的。


    正因如此,C++ 的调用方可以通过一些技巧性转换,“巧妙地”调用到原本无法访问的函数。一个现实的例子是:在 Qt 里面,QObject::event() 函数是 public 的,而其子类 QWidget 的 event() 函数则改变成 protected。具体细节可以阅读 Qt 的相关代码。


    总结来说,在子类覆盖父类函数时,Java 严格限制了子类不能缩小函数可访问性,但 C++ 无此限制。


    个人认为,从软件工程的角度来说,Java 的规定无疑更具有工程上面的意义,函数的调用也更加一致。C++ 的标准则会明显简化编译器实现,但是对工程而言并不算很好的参考。毕竟,一个明显标注了 private 的函数,无论任何情况都不应该允许在外部被调用。


    PS:C++ 标准的正式版是需要购买的,但是草案可以免费下载。C++ 标准草案的下载地址可以在下面的页面找到:https://isocpp.org/std/the-standard


    网友评论:


    @old_big:

    更正几个问题:

    1. ”Java 和 C++ 都是面向对象的语言,允许对象之间的继承“ -- 对象之间都无法继承,继承的是类。javascript等语言才可以集成对象。

    2. ”但是我们的确可以把 Java 的所有函数等同于虚函数,因为 Java 类的所有非 static 函数都可以被子类覆盖“-- java的private实例方法不是虚函数,包访问权限的实力方法在其他包也是无法覆盖,所以此时也不是虚函数。

    3. java中private的方法并不是绝对无法被其他对象访问,反射可以,另外还有一个鲜为人知的方式可以在子类上调用而无需反射。


    @小果汁儿

    C++是个多功能的语言,也就是多范式语言。因为功能多,所以初学者容易滥用功能,出很多问题不知道怎么解决,然后就上网抱怨,从而导致C++现在名声不好。终究归结为一个原因:傻逼太多。C++的面向对象是和其他语言不同的,感兴趣的看一下侯捷的《深入理解C++对象模型》,你就会明白类的对象在内存中怎么存的,继承是怎么继承的。C++的自定义类型有和基本数据类型同等的功能和效率,源于他的运算符重载。要说面向对象是数据结构的重用,那模板就是源码的重用(模板展开,你懂的)。表面的用法没啥探究的,你懂了原理自然豁然开朗。


    @飞鸿眉敛

    "子类对父类函数覆盖时,扩大可访问性,通常都不是问题。"……我的天,这么大的问题居然说没问题?我的Base的指针base指向的是Child的对象,但是我通过base调用sayHello函数的时候,我看到的是Base里sayHello函数的访问权限还是要去找Child里sayHello函数的?很显然我会找的是Base里的,C++明显不允许你扩大访问权限,这才是合理的,因为我看到Base的权限是private或者protected,那我的Base的指针访问这个函数就该是private或者protected,不是吗?


    而当缩小访问权限时,在C++里比如Base的sayHello是public,但是到Child下该函数的访问权限是private了,使用Base的指针访问该函数,同样也是完全可以的,因为对于Base的指针来说sayHello的访问权限就是public。


    综上,很明显C++做到了访问权限的一致性,而且很好的保持了你所说的“工程上的意义”,而Java的权限管理简直是一坨,脚踩西瓜皮,滑到哪里算哪里


    640.jpeg

    • 来源:oschina

    • https://my.oschina.net/editorial-story/blog/1821891

    • 程序员大咖整理发布,转载请联系作者获得授权

    640?wx_fmt=gif640?【点击成为源码大神】

    展开全文
  • 重写(Override)重写是子类父类允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现...
    60da8b9c6efe902093cb4d83a9a89c4f.png

    一.重写(Override)

    重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。即外壳不变,核心重写!重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。在面向对象原则里,重写意味着可以重写任何现有方法.

    方法的重写规则

    • 参数列表必须完全与被重写方法的相同;
    • 返回类型必须完全与被重写方法的返回类型相同;
    • 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。
    • 父类的成员方法只能被它的子类重写。
    • 声明为final的方法不能被重写。
    • 声明为static的方法不能被重写,但是能够被再次声明。
    • 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
    • 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
    • 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以。
    • 构造方法不能被重写。
    • 如果不能继承一个方法,则不能重写这个方法。

    Super关键字的使用

    当需要在子类中调用父类的被重写方法时,要使用super关键字。

    二.重载(Overload)

    重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。最常用的地方就是构造器的重载。

    重载规则:

    • 被重载的方法必须改变参数列表(参数个数或类型不一样);
    • 被重载的方法可以改变返回类型;
    • 被重载的方法可以改变访问修饰符;
    • 被重载的方法可以声明新的或更广的检查异常;
    • 方法能够在同一个类中或者在一个子类中被重载。
    • 无法以返回值类型作为重载函数的区分标准。

    三.重写与重载之间的区别

    区别点重载方法重写方法

    参数列表必须修改一定不能修改

    返回类型可以修改一定不能修改

    异常可以修改可以减少或删除,一定不能抛出新的或者更广的异常

    访问可以修改一定不能做更严格的限制(可以降低限制)

    总结

    方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

    1. 方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
    2. 方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding)。
    3. 方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
    96a9fba56a9902917cd442aadde035d5.png
    展开全文
  • 1.类中前置双下划线__表示私有的,内部不允许访问,意思是只有类对象自己能访问,连子类对象也不能访问。 双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器...
  • 继承:在已有类基础上派生出新的类,已有类被称为父类或基类,新类被称为子类或派生类,子类拥有父类除构造函数、析构函数、赋值运算符重载及静态成员之外的所有成员。通过继承可以复用父类的代码。多态:允许将子...
  • 今天不小心继承一个类型的时候把其中的一个protected的方法写成了public,开始的时候没有发现,后来突然想起来这个方法应该是不提供给访问者的,那么检查竟然发现java编译器允许了这样的行为。想一想,这样的设计还...
  • 方法的名称参数必须完全相同 ...1子类的方法的访问权限可以与父类的不相同,但只允许权限更宽松,而不允许更严格 2返回值的数据类型不相同的情况  是不行的 错误的 编译错误 3final修饰符的不同 若父类方法是final
  • 在外界不允许访问该对象的私有属性class A: def __init__(self):self.num1 = 100 self.__num2 = 200def __test(self):print("私有方法 %d %d" %(self.num1,self.__num2))def test(self):print("这是父类公有方法 ...
  • 一、封装1、概念:将类的某些信息隐藏在类内部,不允许外部程序直接访问,而是通过该类提供的方法来实现对隐藏信息的操作和访问。2、好处:只能通过规定的方法访问数据。隐藏类的实例细节,方便修改和实现。3、封装...
  • 因此对编译器来讲,只允许父类句柄访问父类成员(即父类句柄只能访问子类对象里的父类成员),这样的内存访问方式是安全的。 从图中看,子类句柄赋值给父类句柄,相当于将访问范围从大三角区域限制为小三角区域。...
  • 2. C++ 允许父类指针指向子类对象,父类引用子类对象,无须通过强制类型转换保持赋值类型相容,因为子类对象isa父类对象,编译时按父类说明的权限访问成员; 3. 通过父类指针调用虚函数进行晚期绑定,根据对象的实际...
  • 结论:父类指针可以指向子类对象,但是只能访问父类成员,不能访问子类成员 结论:子类指针不可以指向父类对象,需要类型转换才可以 笔记: <1>.当基类指针指向派生类的时候,只能操作派生类从基类中继承...
  • class Command { public: ...先申明了一个父类的变量 Command cmd; 经过一些处理后 cmd被赋值了一个OnCommand对象 请问如何将cmd转换为OnCommand然后获取里边OnCount属性的值? 不允许这样获取么?
  • 私有继承方式 私有继承中,不允许将子类对象转换成父类对象 ...继承允许子类指针到父类指针的转换,允许子类重写父类虚函数,允许子类访问父类protected成员 选择:尽可能使用组合 构造函数...
  • 如果子类访问父类的构造方法,则在编译的时候提示访问不到该方法。 JAVA中不允许多继承,一个类有且只有一个父类(单继承)。 JAVA的数据结构为树型结构,而非网状。(JAVA通过接口和内部类实现多继承) package
  • 继承是面向对象的三大特征(封装、继承和...可能大家都认同 “当子类继承父类时,子类会获得父类中定义的成员变量和方法,当访问权限允许的情况下,子类可以直接访问父类的变量和方法”。这种观点其实稍显笼统,因为jav
  • 继承:子类可继承父类的所有可访问到的属性与方法; 如若类A是类B的父类,即是类B是类A的子类:class B extends A{ } 父子类间继承时,可造成属性与方法的重写(子类的属性或方法将父类的属性或方法覆盖) 1、注意...
  • 继承: 父类(SuperClass)和子类(SonClass)。...如果子类访问父类的构造方法,则在编译的时候提示访问不到该方法。 JAVA中不允许多继承,一个类有且只有一个父类(单继承)。 JAVA的数据结构为树型...
  • java继承

    2019-12-31 10:47:54
    protected允许子类访问父类的字段和方法; 子类的构造方法可以通过super()调用父类的构造方法; 可以安全地向上转型为更抽象的类型; 可以强制向下转型,最好借助instanceof判断; 子类和父类...
  • protected允许子类访问父类的字段和方法。 子类的构造方法可以通过super()调用父类的构造方法。 可以安全地向上转型为更抽象的类型。 可以强制向下转型,最好借助instanceof判断。 子类和父类的关系是is,...
  • 1.如果子类父类继承时使用的继承限定符是public,那么(1)父类的public成员成为子类的public成员,允许类以外的代码访问这些成员;(2)父类的private成员仍旧是父类的private成员,子类成员不可以访问这些成员;(3)...
  • 继承: 父类(SuperClass)和 子类(SonClass)。 父类的非私有化属性和方法可以默认继承到子类。...如果子类访问父类的构造方法,则在编译的时候提示访问不到该方法。 JAVA中不允许多继承,一个
  • Java基础——可见性修饰符

    千次阅读 2018-07-21 11:53:06
    1. 简介 2. public 3. protected 4. 默认修饰符 5. private 6. 总结 ...可见性修饰符可以用于确定一个类以及他的成员的可见性 ...可以在类、方法、数据源前使用...允许子类访问父类中的数据域或方法,但不允许非子类访...
  • Java核心技术_笔记5-2

    2018-09-04 13:03:55
    1.protected声明的域或方法允许子类访问父类 2. (1)private仅本类可见 (2)public所有类可见 (3)protected本包和所有子类可见 (4)默认 本包可见 3.Object是所有类的超类 可以用object引用任何类型的变量 ...
  • Java访问修饰符

    2020-03-11 20:48:38
    访问权限修饰符 访问级别 ...经常需要允许子类访问定义在父类中的数据和方法,但是不允许非子类访问这些数据和方法,这种情况下就可以使用protected,它允许任何包中的子类访问父类 default...
  • 而private表示它所修饰的实体不允许外部访问,只能在当前类内部访问private成员,即便是子类也不能访问父类的私有成员。这种情况就令人产生了困惑,私人财产当然不会给外人,可是为啥连儿子都无法动用老子的财物呢?...
  • 我有一个通用的集合类,具有各种公共getter方法。 要从集合中获取一个项,请调用get()。还有几种返回多个项目的方法:getmany()、getrange()...我所有的工作都集中在子类中寻找解决方案——我没有考虑更改父类。谢谢!
  • 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类。 继承就是子类继承父类的特征和行为,使得子类...在子类中,访问父类中的成员变量格式: super.父类中的成员变量 例: 1 class ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,395
精华内容 558
关键字:

允许子类访问父类