2011-07-05 45 views
8

我有两个关于C++的问题:关键词“this”的实际含义是什么?

在很多教科书中,关键字this是一个指向调用对象。正确?

正如我想用编码玩,我写了下面简单的代码:

struct Base 
{ 
    void g(); 
    virtual void f(); 
}; 

void Base::f() { 
    cout << "Base::f()" << endl; 
} 

void Base::g() { 
    cout << "Base::g()" << endl; 
    cout << "sizeof(*this) : " << sizeof(*this) << endl; 
    this->f(); 
} 

struct Derived : public Base 
{ 
    int d; 
    void f(); 
}; 

void Derived::f() 
{ 
    cout << "Derived::f()" << endl; 
} 

int main() 
{ 
    Base a; 
    Derived b; 

    cout << "sizeof(a) : " << sizeof(a) << endl; 
    cout << "sizeof(b) : " << sizeof(b) << endl; 

    a.g(); 
    b.g(); 
} 

上面的代码产生以下输出:

sizeof(a) : 4 
sizeof(b) : 8 
Base::g() 
sizeof(*this) : 4 
Base::f() 
Base::g() 
sizeof(*this) : 4 // why 4 bytes not 8 bytes????????? 
Derived::f() 

如果this指向调用对象,如果sizeof(*this)的第二行打印8而不是4,因为调用对象是b?究竟发生了什么? this已被降级?!!!!

如果this已被降级为Basethis->f()如何调用正确的函数?我很困惑。

+0

尝试添加调用为sizeof(*此)的衍生:: F()。看看发布了什么。 Base :: g()中的调用不知道它是子类的一部分。在这种情况下,*这个合法地引用Base,而不是Derived。 –

+0

以及你如何期望'sizeof(* this)'在编译时被评估?它与'sizeof(Base)'没有区别。 –

回答

12
void Base::g() { 
    cout << "Base::g()" << endl; 
    cout << "sizeof(*this) : " << sizeof(*this) << endl; 
    this->f(); 
} 

需要作出的重要区别是sizeof编译时运营商,而不是一个运行时操作。编译器将表达式sizeof(*this)解释为“由this指向的对象的大小”,其在Base::g的范围内将是Base类型的对象。编译器将基本上重写语句这一点,因为它知道的Base大小为四个字节:

cout << "sizeof(*this) : " << 4 << endl; 
+0

哦,你说得对。我修改了代码来打印'this'的值而不是'sizeof(* this)',并且将它与&b和&a进行比较。答案符合我的期望。恩,谢谢你。 – Eto700

0

this是一个常量值指针,指向函数是非静态成员的对象。这意味着,对于this是一个可行的值,它只能用于类的非静态成员。请记住:您必须使用对象实例来调用非静态成员函数(instance.function或instance-> function); this是指向“实例”的指针。

尺寸永远不会是您期望的8的原因是因为g是类Base的成员。对于g,this类型为Base *const,因此*this的类型为Base&sizeof(Base)是4.即使它是虚拟成员,这也不会改变;该实施g的类型将始终为Base *const。几乎被覆盖的版本会有不同的类型,但只有实现它们的类的类型。

this的类型不遵循多态性;它正好和只有函数被定义的类型。

+0

即使'g'是虚拟的,它也无所谓,因为'g'永远不会被派生类覆盖,不是? –

+1

只是为了澄清:即使'g'是虚拟的,无论是通过派生类型调用它,“sizeof(* this)”在Base :: g()中始终为4(例如,如果虚拟'g()'没有被覆盖)。我知道这就是你在最后一句中所说的内容,但第二段可能会让读者认为即使在'g()'的基本实现中'sizeof(* this)'也会'跟随'派生类型。 –

1

Base无法看到/访问/了解任何派生对象的一部分,因此sizeof只报告对其可见的部分对象。更重要的是,在Base的方法中,sizeof无法知道是否存在子类(毕竟,您可以继承子类Base),因此除了知道的部分外,它不能报告任何内容。 (sizeof计算在编译时,不运行时间。)

0

正确的功能f被称为因为Base::f是虚拟的。这告诉编译器,当请求调用Base*->f()时,被调用者的实际地址在你调用其成员的实际对象的vtable中查找。

类型有关thisBase*,这就是为什么sizeof(*this) == sizeof(Base),但其虚表所属的派生对象,因此函数调用f去覆盖。

相关问题