3

I find that the dynamic method dispatching in init method of Swift is different from which in C++, can anyone explain why?

This is the demo code and its output:

In Swift:

class Object {
  init() {
    a()
  }

  func a() {
    print("Object")
  }
}

class SubObject: Object {
    override init() {
    }

    override func a() {
      print("SubObject")
    }
}

let a = SubObject()
// output: SubObject

In C++:

class Object {
public:
    Object() {
        a();
    }

    virtual void a() {
        std::cout << "Object" << std::endl;
    }
};

class SubObject: public Object {
public:
    SubObject() {
    }

    virtual void a() {
        std::cout << "SubObject" << std::endl;
    }
};

int main(int argc, const char * argv[]) {

    SubObject s;

    return 0;
}
// output: Object

As you can see, these code above write in Swift and C++ are nearly the same, but their output is quite different, while Swift seems that it finds the override method and called the derived one, the C++ still called the super's.

Here at LearnCpp, it says:

Do not call virtual functions from constructors or destructors Here’s another gotcha that often catches unsuspecting new programmers. You should not call virtual functions from constructors or destructors. Why?

Remember that when a Derived class is created, the Base portion is constructed first. If you were to call a virtual function from the Base constructor, and Derived portion of the class hadn’t even been created yet, it would be unable to call the Derived version of the function because there’s no Derived object for the Derived function to work on. In C++, it will call the Base version instead.

A similar issue exists for destructors. If you call a virtual function in a Base class destructor, it will always resolve to the Base class version of the function, because the Derived portion of the class will already have been destroyed.

Josscii
  • 110
  • 7
  • Swift designers either didn't understand the design decision made by C++ designers, or (more likely) thought that an average programmer won:t undersand such decision. They chose simplicity over consistency and correctness, or so it seems. Either way, absent a rationale explaining their decision, it's all speculation. – n. m. could be an AI Sep 01 '17 at 06:58
  • But Swift is written by C++, I think they must understand it well, and they just made an another decision. – Josscii Sep 01 '17 at 07:30
  • Personally I find Swift behaviour more consistent. We are creating a SubObject instance and so I would expect `a()` to be called on that SubObject instance. I checked in Java and it produces the same output as Swift (except for the order in which constructors are called). – nyg Sep 01 '17 at 07:57
  • I agree, C++'s behavior seems wired. – Josscii Sep 01 '17 at 08:02
  • So you think C++ is broken, and wonder why Swift fixes it? What is unclear to you exactly? – n. m. could be an AI Sep 01 '17 at 08:53
  • I post this question because I don't understand the init method and the normal methods's dispatching difference. Here, super's init is called before sub' init, why the sub's a() implementation was found? – Josscii Sep 01 '17 at 08:57
  • It's all becoming very unclear very rapidly. What method do you *want* to be called? – n. m. could be an AI Sep 01 '17 at 09:11
  • sorry, I may not explain it well, I will try to figure it out myself, sorry to bother! – Josscii Sep 01 '17 at 09:17

0 Answers0