This
指针在非const成员函数中的类型为ClassName
。
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
对象,那么您只需指向整个{{1}中存在该方法的offset
object layout
1}}从address
中的pointer
开始到object
。
但是,如果我在derived
类方法中拥有start
的{{1}}地址,为什么我无法偏移到(derived)object
类方法。
由于上述理解,我无法理解为什么我不能这样做。我错过了一些非常基本的东西。
答案 0 :(得分:7)
让我们假设你是一个编译器。现在你看到这个类:
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>
可能会提供这样的功能。
答案 1 :(得分: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;
}
答案 2 :(得分:5)
Me:当编译器编译Base :: get函数时,它看不到Derived :: put函数。
你:Derived ::不是放在同一个文件中吗?为什么编译器不能看到它?
我:如果有人在4年之后定义的Derived1 :: putttttt从另一个文件中的Base派生怎么办?
你:mm,也许我明白了。
答案 3 :(得分:2)
类Base
不知道您只是将它用作Derived
对象的一部分;通常,可能有许多不同的派生类,只有一个或部分可能有put()
。怎么可以编译Base
呢?
当你有一个指向Base
对象的Derived
指针时,你可以投射它以获得指向Derived
的指针,并以这种方式调用方法:
Base* b = new Derived;
dynamic_cast<Derived*>(b)-> put();
如果需要,类实际上可以将this
强制转换为派生实例ponter:
dynamic_cast<Derived*>(this)-> put();
答案 4 :(得分:1)
考虑一下你在基类中编写了this->put()
方法,在编译期间编译器会检查同一个类中的put()函数,因为你没有这样的,它会显示编译时错误
答案 5 :(得分:1)
您发布的代码将无法编译,因为编译器在编译derived
的代码时不知道class Base
类是什么。 this
指针是一个指针,它隐式传递给类的每个非静态成员函数,该函数如何访问它的实例的成员属性。在Base
类成员函数this
中,类型为Base *
在const
成员函数中,它将具有const Base *
类型。
此外,this
是非l值,表示您无法为其赋值。
以下是关于this指针的C ++标准:
9.3.2这个指针
在非静态(9.3)成员函数的主体中,关键字this是一个值为prvalue的表达式 是调用该函数的对象的地址。这个类型在一个成员函数中 X类是X *。如果成员函数声明为const,则其类型为const X *,如果是成员 函数声明为volatile,其类型为volatile X *,如果声明了成员函数 const volatile,这个类型是const volatile 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
我建议使用虚拟功能或模板来获得所需的行为。