3

This指针的类型为ClassNamein 非常量成员函数。

 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;
 }

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

同样据我所知,如果您pointer在调用它的方法时有一个 to 对象,那么您只是指向offset该方法在整体中的位置,object layout从 to 的address现在pointer开始object

derived但是当我有类方法的start地址时,为什么我不能偏移到(derived)objectbase方法。

由于上述理解,我无法理解为什么我不能这样做。我在这里遗漏了一些非常基本的东西。

4

6 回答 6

8

让我们想象一下你是一个编译器。现在你看到这个类:

class foo
{
    void bar() { this->xyz(); }
};

你做什么工作?你抱怨你不知道是什么xyz,而且它肯定不是foo. 您不必四处寻找其他类并检查它们是否可能派生自foo并声明此函数-它只会反过来起作用。

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

class foo
{
    void bar() { this->xyz(); }
    virtual void xyz() = 0;
};

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

但是请注意,这确实适用于模板:

template <typename T>
class foo
{
    void bar() { t.xyz(); }
    T t;
};

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

于 2013-08-08T13:07:37.143 回答
6

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

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

我:如果有一个 Derived1::putttttt 是 4 年后某人从另一个文件中派生的 Base 定义的呢?

你:嗯,也许我明白了。

于 2013-08-08T13:09:57.750 回答
5

您必须将您的方法 put() 声明为虚拟的。

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;
}
于 2013-08-08T13:05:55.253 回答
2

Base不知道您只会将其用作Derived对象的一部分;通常,可能有许多不同的派生类,其中只有一个或一些可能具有put(). 那怎么可能Base编译呢?

当您有一个Base指向Derived对象的指针时,您可以其强制转换以获得指向 的指针Derived,并以这种方式调用该方法:

Base* b = new Derived;
dynamic_cast<Derived*>(b)-> put();

如果需要,一个类实际上可以this转换为派生实例:

dynamic_cast<Derived*>(this)-> put();
于 2013-08-08T13:05:29.627 回答
1

考虑您this->put()在基类中编写了方法,在编译期间,编译器会检查同一类中的 put() 函数,因为您没有此类函数,它会显示编译时错误。

于 2013-08-08T13:23:04.583 回答
1

您发布的代码将无法编译,因为编译器derived在编译class Base. this指针是一个隐式传递给类的每个非静态成员函数的指针,它表明该函数如何访问它的实例的成员属性。在Base类中,成员函数this具有类型Base *const成员函数中,它将具有类型const Base *

也是this一个非左值,这意味着你不能给它赋值。

以下是关于 this 指针的 C++ 标准:

9.3.2 this 指针

在非静态 (9.3) 成员函数的主体中,关键字 this 是一个纯右值表达式,其值是调用该函数的对象的地址。类 X 的成员函数中 this 的类型是 X*。如果成员函数声明为 const,则 this 的类型为 const X*,如果成员函数声明为 volatile,则 this 的类型为 volatile X*,如果成员函数声明为 const volatile,则 this 的类型为 const挥发性 X*。

现在,至于在您的问题中做您想做的事情,以下编译

#include <iostream>
class Base
{
   public:
     void get();
};


class derived: public Base
{
   public:
   void put()
   {
        std::cout << "This is a bad idea" << std::endl;

   }
};


void Base::get()
{
    //compiler knows what dervied class is
    static_cast<derived *>(this)->put();  
}


 int main()
 {
    derived d;
    d.get();

    return 0;
 }

输出是:This is a bad idea

我建议使用虚函数或模板来获得所需的行为。

于 2013-08-08T13:31:30.653 回答