精华内容
下载资源
问答
  • 假设基类(父类)是Base,派生(子类)是...但实际上这是错误的,这样得到的派生类指针是不能指向派生的成员函数或者数据成员。 而应该使用reinterpret_cast强制类型转换进行转换。 Derived d; Base *bp =...

    假设基类(父类)是Base,派生类(子类)是Derived。

    之前用到在网上查都说用

    Derived d;
    Base *bp = &d;
    Derived *dp = (Base*)bp;

    但实际上这是错误的,这样得到的派生类指针是不能指向派生类的成员函数或者数据成员。

    而应该使用reinterpret_cast强制类型转换进行转换。

    Derived d;
    Base *bp = &d;
    Derived *dp = reinterpret_cast<Derived *> bp;

    《C++程序设计思想与方法(慕课版)》:这(强制类型转换)等于告诉编译器:我知道这个危险,但我保证不会出问题。reinterpret_cast是一种相当危险的转换,它让系统按程序员的意思解释内存中的信息。

    展开全文
  • 当B指针指向A对象时(当B存在新增数据成员时可能出错),同理。 而对于普通函数则受类型的制约,(因为没有vptr指针)使用哪个的指针调用函数,那么所调用的就是那个累的函数。 总而言之,普通函数...
    源程序:#include <iostream.h>
    
    class A
    {
    public:
       virtual void F1()
     {
      cout<<"A1"<<endl;
     }
     void F2()
     {
      cout<<"A2"<<endl;
     }
    
    };
    class B :public A
    {
    public:
     void F1()
     {
      cout<<"B1"<<endl;
     }
     void F2()
     {
      cout<<"B2"<<endl;
     }
    
    };
    void main(){
    
     A *pa;
     B *pb;
     B TB;
     A TA;
    
     pa = &TB;//基类指针指向派生类对象
     pa->F1();
     pa->F2();
    
     pb =(B *) &TA;//派生类指针指向基类对象
    
     pb->F1();
     pb->F2();
    
    }
    
      
    以上程序输出结果:
    B1
    A2
    A1
    B2
    解释一下: 一个类所有的函数都是再code代码区中唯一的存放一份。而数据成员则是每个对象存储一份,并按照声明顺序依次存放。 类A中有了虚函数就会在类的数据成员的最前面添加一个vfptr指针(void** vfptr),这个指针用来指向一个vtable表(一个函数指针数组)(一个类只有一个该表),该表存储着当前类的所有虚函数的地址。这样vfptr就成为了一个类似成员变量的存在。访问虚函数的时候通过vfptr间址找到vtable表,再间址进而找到要调用的函数。这样就在一定程度上摆脱了类型制约。 基类在定义并实现了自己的虚函数后,在全局内存区域中(可以这么理解),会有一个虚函数表,里面都是已实现的函数的指针。程序运行过程中实例化的所有基类对象,都有一个指向虚函数表的指针,而且这个指针的值是一样的,都指向那个全局内存。因为对于基类的每个实例他们使用的函数代码都是一样的嘛。当你定义了一个派生类,并重新实现了部分虚函数后,由于你实现的虚函数和基类不同,所以必须有另一块全局内存保存派生类的虚函数指针列表。最简单的派生情况下,你的派生类就是在基类的内存块之后又加了些派生类使用的内存,此种最简单的情况下,你的派生类其实可以直接使用基类的那个指向虚函数列表的指针,只是指针的值是不同的而已。它指向不是基类的虚函数列表,而是派生类的虚函数列表。如果你没有定义新的虚函数,那么派生类的虚函数列表和基类布局一样,只是函数地址值不同,否则会在后面增加你新定义的函数的地址。 通过以上分析,我感觉如果你的派生类不对基类的虚函数做任何重新实现或补充,理论上可以使用同一个虚函数表,否则不行。 只要vptr的值不同,那么访问函数成员的时候使用的vtable表就不同,就可能访问到不同类的函数成员。B类对象中的vptr指向B类自己的vtable。当B类继承A类的时候,因为A中有虚函数,编译器就自动的给B类添加vfprt指针和vtable表。也可以理解为B类继承来了A类中的那个vptr指针成员。 当A类指针指向B类对象时,发生假切割。要知道这个过程只是切掉A类中没有的那些成员,由于vptr是从A类中继承来的,所以这个量仍将保留。而对于vptr的值则不会改变,仍然指向B类的vtable表。所以访问F1函数的时候是通过B类的vtable表去寻址的,自然就是使用子类的函数。 当B类的指针指向A类的对象时(当B类存在新增数据成员时可能出错),同理。 而对于普通函数则受类型的制约,(因为没有vptr指针)使用哪个类的指针调用函数,那么所调用的就是那个累的函数。 总而言之,普通函数通过对象或指针的类型来找所调用的函数,而虚函数是通过一个指针来找到所要调用的函数的。

    转自https://blog.csdn.net/hehe6378/article/details/40267603

    展开全文
  • 1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础定义的函数(静态联翩) 2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作(explicit cast),这种做法...

    父类子类指针函数调用注意事项
    1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础类定义的函数(静态联翩)
    2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作(explicit cast),这种做法很危险,也不符合生活习惯,在程序设计上也会给程序员带来困扰。(一般不会这么去定义)
    3,如果基础类和衍生类定义了相同名称的成员函数,那么通过对象指针调用成员函数时,到底调用那个函数要根据指针的原型来确定,而不是根据指针实际指向的对象类型确定。

    [cpp]  view plain  copy
    1.  class A  
    2. {  
    3. public:   
    4. virtual void show()  
    5. {  
    6. cout<<" show A"<<endl;  
    7. }  
    8. void display(){  
    9. cout<<"display A"<<endl;  
    10. }  
    11. };  
    12. class B:public A  
    13. {  
    14. public:  
    15.  virtual void show()  
    16. {  
    17. cout<<" show B"<<endl;  
    18. }  
    19. void display(){   
    20. cout<<"display B"<<endl;  
    21. }  
    22. };  
    23. int main()    
    24. {    
    25. A *bb=(A*)new B();  
    26. bb->display();  
    27. static_cast<B*>(bb)->display();  
    28. bb->show();  
    29.   
    30. B *aa=(B*)new A();//(子类指针指向父类对象地址)必须强转才行  
    31. aa->display();  
    32. static_cast<A*>(aa)->display();  
    33. aa->show();  //此时aa指向的父类对象的内存空间,所以只能调用父类中函数。如果用aa调用子类B中特有的函数还会出错,内存中不存在。此时不是多态哦  
    34.   
    35. return 0;  
    36.   
    37. }  




    虚拟函数就是为了对“如果你以一个基础类指针指向一个衍生类对象,那么通过该指针,你只能访问基础类定义的成员函数”这条规则反其道而行之的设计。
    如果你预期衍生类由可能重新定义一个成员函数,那么你就把它定义成虚拟函数( virtual )。
    polymorphism就是让处理基础类别对象的程序代码能够通透的继续适当地处理衍生类对象。
    纯虚拟函数:
    virtual void myfunc ( ) =0;
    纯虚拟函数不许定义其具体动作,它的存在只是为了在衍生类钟被重新定义。只要是拥有纯虚拟函数的类,就是抽象类,它们是不能够被实例化的(只能被继承)。如果一个继承类没有改写父类中的纯虚函数,那么他也是抽象类,也不能被实例化。
    抽象类不能被实例化,不过我们可以拥有指向抽象类的指针,以便于操纵各个衍生类
    虚拟函数衍生下去仍然是虚拟函数,而且还可以省略掉关键字“virtual”。
    看个例子:

    [cpp]  view plain  copy
    1. #include <iostream>   
    2. using namespace std;   
    3. class A   
    4. {   
    5. public:   
    6.     virtual void foo()   
    7.     {   
    8.         cout << "A's foo()" << endl;   
    9.         bar();   
    10.     }   
    11.     virtual void bar()   
    12.     {   
    13.         cout << "A's bar()" << endl;   
    14.     }   
    15. };   
    16. class B: public A   
    17. {   
    18. public:   
    19.     void foo()   
    20.     {   
    21.         cout << "B's foo()" << endl;   
    22.         A::foo();   
    23.     }   
    24.     void bar()   
    25.     {   
    26.         cout << "B's bar()" << endl;   
    27.     }   
    28. };   
    29. int main()   
    30. {   
    31.     B bobj;   
    32.     A *aptr = &bobj;   
    33.     aptr->foo();   
    34.     A aobj = *aptr; //转化为A类对象  
    35.     aobj.foo();   
    36. }   


    aptr->foo()输出结果是:
       B's foo()//这个明白,多态性
       A's foo()//这个也明白,执行A::foo();
      B's bar()//虽然调用的是这个函数:A::foo(); 但隐式传入的还是bobj 的地址(bar()的前面有个this指针)
    , 所以再次调用bar();调用时还是会调用B的函数, 与虚函数指针有关
    aobj.foo()输出结果是:
      A's foo() //这个不是指针,aobj完全是一个A的对象,与多态没有关系
      A's bar() 
    展开全文
  • 访问指向类指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。 与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 C++的精髓之一就是多态性,只有指针或者引用可以达到多态。...

    一个指向 C++ 类的指针与指向结构的指针类似,
    访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。
    与所有的指针一样,您必须在使用指针之前,对指针进行初始化。

    C++的精髓之一就是多态性,只有指针或者引用可以达到多态。对象不行

    用指针:
    第一实现多态。
    第二在函数调用,传指针参数。不管你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节。如果用对象,参数传递占用的资源就太大了

    类的指针:他是一个内存地址值,他指向内存中存放的类对

    展开全文
  • 基类指针指向派生类对象

    千次阅读 2015-10-19 17:55:20
    所以,将派生类指针指向基类对象的时候要进行显示的强制转换,否则会使基类对象中的派生成员成为未定义的。 总结:基类指针和派生类指针指向基类对象和派生类对象的4中方法: 1. 基类指针指
  • 1、B指针指向A对象 首先看这么一个例子: #include &amp;amp;amp;amp;amp;amp;lt;iostream&amp;amp;amp;amp;amp;amp;gt; using namespace std; class A{ public: A(){ a = 1; b = 2; } ...
  • 派生类指针 基类对象 简单:利用基类指针调用 来调用基类函数 编译错误,是一个关系,也就是继承关系有方向性。 派生类对象 安全:派生类对象也是一个基类对象 只能调用基类成员函数;如果调用派生...
  • c++父类指针指向子类对象

    千次阅读 2018-11-08 15:50:04
    1,如果以一个基础类指针指向一个衍生类对象(派生类对象),那么经由该指针只能访问基础定义的函数(静态联翩) 2,如果以一个衍生类指针指向一个基础类对象,必须先做强制转型动作(explicit cast),这种做法很...
  • 《C++ Primer》第五版,中文版。p50。 需要注意的是,一个指针指向对象,同时另一个指针指向另外对象的下一地址,此时也有可能出现这两个指针值相同的情况,即指针相等。
  • 为什么需要基类指针指向派生类对象? 我们知道虚函数可以让我们的具备多态的功能,你肯定在此会有所疑惑,为什么需要基类指针指向派生类对象?派生指针自己就能实现的功能,何必基类指针来多此一举呢?其实这...
  • 基类指针指向子类对象

    千次阅读 多人点赞 2018-07-03 10:10:44
    没有指定虚函数, 那么它就只能访问到类型对应的函数基类指针...正常情况,子类祖先的析构函数都是虚拟的,这样删除祖先类指针、子类对象的时候,可正确同时调用子类和祖先的析构函数):#include &lt;iost...
  • 在基类与派生之间,有一个规定:派生类对象的地址可以赋给指向基类对象指针变量(简称基类指针),即基类指针也可以指向派生类对象。为什么有这一规定呢?因为它可以实现多态性【1】,即向不同的对象发送同一个...
  • 1 前言 记得当初阿里面试的时候被问道这个问题,平时自己面对这个方法都习以为常的使用,C++多态和动态绑定不就是这么实现的嘛,但是还真没有刻意... 如果以一个派生类类指针指向一个基础类对象,必须先做强制转型动作
  • C++ 基类指针指向派生类对象

    万次阅读 2014-03-02 17:06:47
    指向派生类对象指针可以转换为指向基类对象指针,但是只能引用基类成员。 #include using namespace std; class A { int x; public: A(int i){x=i;} void dispa(){cout;} }; class B:public A { int y;...
  • 1 对象数组     对象数组是指数组元素为对象的数组。这种对象数组与其它数据类型的数组定义方式相同。... C++语言不允许初始化对象数组,所以要创建一个对象数组,这个必须具备以下三个条件

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 564,082
精华内容 225,632
关键字:

如何用指针指向类对象