【问题标题】:virtual function, -> operator, inheritance SO CONFUSING虚函数,-> 运算符,继承 SO CONFUSING
【发布时间】:2013-03-21 03:22:44
【问题描述】:

好吧,这是一个让我很困惑的简单例子......

class First { public: void Func() {cout<<"FirstFunc";} };
class Second : public First
    { public: void Func() {cout<<"SecondFunc";} };
class Third : public Second
    { public: void Func() {cout<<"ThirdFunc";} };

int main () {
   Third * thirdptr = new Third();
   Second * secondptr = thirdptr;
   First * firstptr = secondptr;

   firstptr->Func();  // prints out FirstFunc
   secondptr->Func();  // prints out SecondFunc
   thirdptr->Func();  // prints out ThirdFunc

   delete thirdptr;

这是带有虚函数的

class First { public: virtual void Func() {cout<<"FirstFunc";} };
class Second : public First
    { public: virtual void Func() {cout<<"SecondFunc";} };
class Third : public Second
    { public: virtual void Func() {cout<<"ThirdFunc";} };

int main () {
   Third * thirdptr = new Third();
   Second * secondptr = thirdptr;
   First * firstptr = secondptr;

   firstptr->Func();  // prints out ThirdFunc
   secondptr->Func();  // prints out ThirdFunc
   thirdptr->Func();  // prints out ThirdFunc

   delete thirdptr;

好的,这是我的问题。

  1. 如何读取 Third *thirdptr = new Third(); new 在“new int”时为 int 分配内存 但我不知道我应该如何阅读 new Third();因为它是构造函数

  2. 第二 * secondptr = thirdptr; / 第一 * firstptr = secondptr; 这两种说法太混乱了。 任何人都可以用 & 运算符或与地址运算符相关的简单词语来解释它吗? 我理解这个指针和继承的概念,但这部分太混乱了。

  3. 我应该如何从第二个示例中获得结果? 我正在读的书是在说

第一个例子 // C++ 编译器关于指针算术运算,做出决定 // 基于指针的类型,而不是指针实际指向的内容

第二个例子 // VIRTUAL FUNCTION : 决定,不基于指针类型 //,根据指针实际指向的内容调用什么

这是翻译,可能不准确,但还是看不懂。 如果您能帮助我,我将不胜感激!

【问题讨论】:

    标签: c++ function pointers inheritance overriding


    【解决方案1】:
    1. new Third() 做了两件事。首先它为Third 对象分配内存,然后调用Third 上的构造函数。您可以认为该语句分为两部分,new Third 分配内存和() 调用构造函数。

    2. Second * secondptr = thirdptr; / First * firstptr = secondptr; 所有三个变量都分配给同一个指针。假设thritptr 等于100。那么secondptrfirstptr 在这些语句的末尾都等于100。所有三个指针都指向内存中的相同地址。但是,由于它们是不同的类型,因此编译器会将它们解释为不同的

    3. 对于非虚拟函数,方法调用在编译时根据变量的类型进行解析。因此,当编译第一个代码firstptr 的类型为First* 时,编译器会生成对First::Func() 的调用。对于虚函数,方法调用直到运行时才完全解析。编译器生成的代码将确定变量指向的实际类型并调用该函数。在第二个例子中,当程序运行时,firstpr-&gt;Func()首先确定firstptr确实指向一个Thrird对象,所以它调用Third::Func()。这通常使用virtual function table 来完成。

    【讨论】:

      【解决方案2】:

      为了回答您的第一个问题,new Third() 在高层次上与new int 做同样的事情。正如您所说,new int 将为int 分配内存,左侧的指针将指向该内存。 new Third()Third 对象分配内存,并使用Third 类的默认构造函数Third() 对其进行初始化。

      对于第二个问题,您正在创建三个指针并将它们全部指向同一个内存块。我相信由于继承,可以将每个指针类型隐式转换为更高的类型(没有显式指令的隐式转换含义,例如 static_cast 或 C 样式转换)。视觉上:

      ----
      |  | <-- Some block of memory.
      ----
      
      A -> ---- <-- A* aptr = new A();
           |  |
           ----
      
      A -> ----
      B -> |  | <-- B* bptr = aptr;
           ----
      
      A -> ----
      B -> |  |
      C -> ---- <-- C* cptr = bptr;
      

      注意所有三个指针如何指向同一个内存块。 (另请注意,指针都指向内存的开始 - 完全相同的位置。很难在上面描述。)

      关于你的第三个问题:

      决定,不根据指针类型,根据什么来调用什么 指针实际上是指向

      意味着编译器将根据内存中对象的实际类型而不是指向内存的指针的类型来决定调用哪个函数实例。因此,在您的示例中,您创建了一个Third 类型的对象,并有三个指向它的指针,类型为FirstSecondThird。不管指针类型如何,因为Func 是虚拟的,所以ThirdFunc 版本会被执行,因为内存中的对象是Third 类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-08
        • 2015-06-27
        相关资源
        最近更新 更多