当调用派生类对象时,为什么`this`无法从基类方法访问派生类成员

Uch*_*chi 2 c++ inheritance

This指针具有ClassName非const成员函数的类型.

 class Base
 {
   public:
     void get()
     {
       //this->put(); Why can't I call back a derived class method eventhough 
                       **this** is pointing to derived class object.
     }
 };

 class derived: public Base
 {
   public:
   void put()
   {
    // do somthing.
   }
 };

 int main()
 {
  derived d;
  //d.get();
  d.put();
  return 0;
 }
Run Code Online (Sandbox Code Playgroud)

如果我this在两个函数中打印指针的值都是相同的,表明它是为派生类对象调用的.this指针类型也在derived *这里.

此外,作为我明白,如果你有一个pointer当你调用它的方法,那么你只是指着反对offset,其中方法是目前在整个object layout从开始address存在于pointerobject.

但是,为什么我不能抵消的derived类方法时,我有start地址(derived)objectbase类方法.

由于上述理解,我无法理解为什么我不能这样做.我错过了一些非常基本的东西.

nij*_*sen 7

让我们假设你是一个编译器.现在你看到这个类:

class foo
{
    void bar() { this->xyz(); }
};
Run Code Online (Sandbox Code Playgroud)

你是做什么?你抱怨你不知道是什么xyz,它肯定不是一个成员的功能foo.你不去寻找其他类并检查它们是否可以派生出来foo并声明这个函数 - 它只能反过来.

反过来意味着您必须声明希望派生类实现的方法的签名:

class foo
{
    void bar() { this->xyz(); }
    virtual void xyz() = 0;
};
Run Code Online (Sandbox Code Playgroud)

突然,这是有效的,但现在你不能再创建一个实例foo了:每个具有纯虚方法的类都是一个抽象类.

但是请注意,这为模板的工作:

template <typename T>
class foo
{
    void bar() { t.xyz(); }
    T t;
};
Run Code Online (Sandbox Code Playgroud)

因为每个模板都是在编译时实例化的,所以你不会看上面的模板,但是例如foo<xyz_class>可能提供这样的功能.


小智 5

您必须将方法put()声明为virtual.

class Base
{
public:
     virtual void put() = 0;
     void get()
     {
       //this->put(); Why can't I call back a derived class method eventhough 
                       **this** is pointing to derived class object.
     }
};

class derived: public Base
{
public:
    void put()
    {
    // do somthing.
    }
};

int main()
{
    derived d;
    //d.get();
    d.put();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)


Per*_*est 5

我:当编译器编译Base :: get函数时,它看不到Derived :: put函数.

你:Derived ::不是放在同一个文件里吗?为什么编译器看不到呢?

我:如果有人在4年之后定义的Derived1 :: putttttt从另一个文件中的Base派生怎么办?

你:mm,也许我明白了.