2016-08-02 122 views
0

我试图理解虚函数,并且遇到以下代码。将派生类构造函数分配给基类指针

class Base 
{ 
    public: 
      void Method1() { std::cout << "Base::Method1" << std::endl; } 
    virtual void Method2() { std::cout << "Base::Method2" << std::endl; } 
}; 

class Derived : public Base 
{ 
    public: 
    void Method1() { std::cout << "Derived::Method1" << std::endl; } 
    void Method2() { std::cout << "Derived::Method2" << std::endl; } 
}; 

Base* obj = new Derived(); 
    // Note - constructed as Derived, but pointer stored as Base* 

obj->Method1(); // Prints "Base::Method1" 
obj->Method2(); // Prints "Derived::Method2" 

到底,如何用派生类构造函数初始化一个基类指针?

+2

相关:http://stackoverflow.com/questions/4937180/a-base-class-pointer-can-point-to-a-derived-class-object-why-is-the-vice-versa – NathanOliver

回答

3

C++允许从派生指针类型到基指针类型的隐式转换。这是安全的,因为派生类型的内存布局与基类的基本大小相同。

虽然您的例子有一个潜在的错误,因为您已经失去了对obj的真实类型的跟踪。当需要删除它时,你会调用错误的析构函数。这可以通过使析构函数为虚拟来弥补。

0

它被初始化为对构造函数的调用结果。调用新的Derived()将创建一个指向新派生对象的指针。 并且由于类Derived从类Base公开派生,所以指向的新对象是一个基础(同时也是派生的)。

0

对于表达...

obj->Method1(); // Prints "Base::Method1" 

...的编译看到的指针的Base实例对象。它寻找一种叫做Method1的方法。它发现它是非虚拟的方法的。所以它会静态地绑定它(也就是在编译时)并生成“直接”调用Base::Method1的代码。

对于表达...

obj->Method2(); 

...编译器看到的指针的Base实例对象。它寻找一种叫做Method2的方法。它发现它是一个虚拟方法。所以它不会静态地绑定它(也就是在编译时),但是会生成代码,用于运行时查找实例对象obj指向的实际类。在运行时间有一个Derived的实例对象。因此Derived::Method2将被找到并执行。

让我们总结了与伟大阿兰凯的报价:

其实我提出了术语“面向对象”,我可以告诉你,我没有C++的初衷。

相关问题