我试图理解虚函数,并遇到了以下代码。
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"
接下来,如何使用派生类Constructor初始化Base类指针?
答案 0 :(得分:3)
C ++允许从派生指针类型到基指针类型的隐式转换。这是安全的,因为派生类型的内存布局与基类的内存大小相同。
你的例子有一个潜在的错误,因为你已经忘记了obj
的真实类型。当需要删除它时,您将调用错误的析构函数。这可以通过使析构函数虚拟来解决。
答案 1 :(得分:0)
使用对构造函数的调用结果初始化它。 调用new Derived()会创建一个指向新Derived对象的指针。 并且由于类Derived从类Base公开派生,所指向的新对象是一个基础(同时作为派生)。
答案 2 :(得分:0)
表达式......
obj->Method1 (); // Prints "Base::Method1"
... 编译器看到指向Base
的实例对象的指针。它查找名为Method1
的方法。它将其视为非虚拟方法。所以它静态地绑定它(也就是在编译时),并生成直接&#34;直接&#34;致电Base::Method1
。
表达式......
obj->Method2 ();
...编译器看到指向Base
的实例对象的指针。它查找名为Method2
的方法。它将其视为虚拟方法。因此它不会静态绑定它(也就是在编译时),但会在实例对象obj
指向的实际类上生成运行时查找代码。在运行时,有一个Derived
的实例对象。因此,Derived::Method2
将被找到并执行。
让我们用伟大的Alan Kay的一句话来概括:
实际上我编写了术语&#34;面向对象&#34;,我可以告诉你我没有考虑到C ++。