指针不继承基础 class 方法
Pointer not inheriting base class methods
我刚开始学习多态性,但被 smth 卡住了。我有一个基础 class Object
和一个派生 class Ball
。我想实现多态性并在 Object
指针上使用 Ball
方法:
Object *ball = new Ball(P, dPdt, s, Forces);
cout << ball->getP() << " position\n" << ball->getdPdt() << " speed\n";
第一个 getP()
工作正常,因为它是 Object
class 和 Ball
的构造函数调用 Object
的方法构造函数来初始化它。现在,当谈到 getdPdt()
时,编译会抱怨 在 Object
中没有名为 getdPdt
的成员,这很明显,因为我在 Ball
。我 doing/understanding 哪里错了?
PS: 我需要 *ball
成为一个 Object
因为这是一个物理模拟,一切都必须是 Object
为了模拟它。稍后,我想我会添加一个 vector<unique_ptr<Object>>
来跟踪
如果 Object
是多态类型,一个快速而肮脏的解决方案是向下转型。
Object *ball = new Ball(P, dPdt, s, Forces);
dynamic_cast<Ball*>(ball)->getdPdt();
这只有在您确定 ball
指向一个 Ball
对象时才有效。否则,必须在对已转换的指针调用 getdPdt
之前进行检查。
请注意,上述解决方案违背了您想要实现的 多态性 目标。多态性是关于为不同类型的实体(在本例中是 [=12= 的所有子class,包括Ball
)。界面的设计应使所有必需的操作都可以通过 Object*
.
访问
如果为 Object
定义 getdPdt
有意义,则更好的多态解决方案:
class Object {
public:
virtual int getdPdt() const {
return 0;
}
};
class Ball : public Object {
public:
int getdPdt() const override {
return 42;
}
};
int main() {
Object* obj = new Ball();
// this returns 42, despite obj being `Object*`
obj->getdPdt();
}
C++ 是一种静态类型语言。如果表达式的 static 类型是 Object
,那么它可以做任何 Object
可以做的事情(除此之外别无他法)。如果它是 Ball
,那么它可以做 Ball
可以做的任何事情。你希望它是一个 Object
但能够做 Ball
可以做的事情。你不能两者兼得,你需要选择一种方式。
多态性并不是让专门为 Ball
定义的属性通过 Object
指针神奇地可用。它是关于 Ball
从 Object
继承的属性以 Ball
特定的方式运行。
注意
Object *ball = new Ball(P, dPdt, s, Forces);
dynamic_cast<Ball*>(ball)->getdPdt();
只能这样读:
Object *ball = new Ball(P, dPdt, s, Forces);
// I want to create a Ball but forget that it's a Ball
// I want to only remember that it's an Object
dynamic_cast<Ball*>(ball)->getdPdt();
// No! It's really a Ball after all!
// My decision to forget it was wrong! I regret it!
现在任何人看到这两行代码都会想知道你是否真的知道你想要什么,这是理所当然的。不要在下一行做你后悔的事情。
如果这两条线不相邻,情况就更复杂了。例如,您可能有一个向量 Object*
:
std::vector<Object*> objects;
objects.push_back(new Ball(whatever));
// in a totally different function in a totally different file
dynamic_cast<Ball*>(objects[i])->getdPdt();
现在,精明的 reader 会问的问题有所不同,但同样困难。为什么知道objects[i]
指向一个Ball
?为什么这些知识不以变量的类型编码?这就是 C++ 中的类型。回想一下,C++ 是一种静态类型语言。对此的任何例外(并且 dynamic_cast
自然是一个例外,其中包含“动态”一词)应该是非常合理的。如果有一些代码根据变量的类型决定做什么,那么该代码通常应该是基类 class.
中的一个方法。
最后,在 object-oriented 设计范例中,您只能做两件不同的事情。要么将 getdPdt
添加到 Object
,以便它可用于所有 Object
;或者将您的 Ball
放在一个单独的篮子中,篮子的类型表明里面有 Ball
,而不仅仅是 Object
。 dynamic_cast
是对 OO 范式的偏离。一个偏差是否可以接受由你决定,但如果你发现自己偏离它很多,那么也许你想考虑一个不同的范例。
我刚开始学习多态性,但被 smth 卡住了。我有一个基础 class Object
和一个派生 class Ball
。我想实现多态性并在 Object
指针上使用 Ball
方法:
Object *ball = new Ball(P, dPdt, s, Forces);
cout << ball->getP() << " position\n" << ball->getdPdt() << " speed\n";
第一个 getP()
工作正常,因为它是 Object
class 和 Ball
的构造函数调用 Object
的方法构造函数来初始化它。现在,当谈到 getdPdt()
时,编译会抱怨 在 Object
中没有名为 getdPdt
的成员,这很明显,因为我在 Ball
。我 doing/understanding 哪里错了?
PS: 我需要 *ball
成为一个 Object
因为这是一个物理模拟,一切都必须是 Object
为了模拟它。稍后,我想我会添加一个 vector<unique_ptr<Object>>
来跟踪
如果 Object
是多态类型,一个快速而肮脏的解决方案是向下转型。
Object *ball = new Ball(P, dPdt, s, Forces);
dynamic_cast<Ball*>(ball)->getdPdt();
这只有在您确定 ball
指向一个 Ball
对象时才有效。否则,必须在对已转换的指针调用 getdPdt
之前进行检查。
请注意,上述解决方案违背了您想要实现的 多态性 目标。多态性是关于为不同类型的实体(在本例中是 [=12= 的所有子class,包括Ball
)。界面的设计应使所有必需的操作都可以通过 Object*
.
如果为 Object
定义 getdPdt
有意义,则更好的多态解决方案:
class Object {
public:
virtual int getdPdt() const {
return 0;
}
};
class Ball : public Object {
public:
int getdPdt() const override {
return 42;
}
};
int main() {
Object* obj = new Ball();
// this returns 42, despite obj being `Object*`
obj->getdPdt();
}
C++ 是一种静态类型语言。如果表达式的 static 类型是 Object
,那么它可以做任何 Object
可以做的事情(除此之外别无他法)。如果它是 Ball
,那么它可以做 Ball
可以做的任何事情。你希望它是一个 Object
但能够做 Ball
可以做的事情。你不能两者兼得,你需要选择一种方式。
多态性并不是让专门为 Ball
定义的属性通过 Object
指针神奇地可用。它是关于 Ball
从 Object
继承的属性以 Ball
特定的方式运行。
注意
Object *ball = new Ball(P, dPdt, s, Forces);
dynamic_cast<Ball*>(ball)->getdPdt();
只能这样读:
Object *ball = new Ball(P, dPdt, s, Forces);
// I want to create a Ball but forget that it's a Ball
// I want to only remember that it's an Object
dynamic_cast<Ball*>(ball)->getdPdt();
// No! It's really a Ball after all!
// My decision to forget it was wrong! I regret it!
现在任何人看到这两行代码都会想知道你是否真的知道你想要什么,这是理所当然的。不要在下一行做你后悔的事情。
如果这两条线不相邻,情况就更复杂了。例如,您可能有一个向量 Object*
:
std::vector<Object*> objects;
objects.push_back(new Ball(whatever));
// in a totally different function in a totally different file
dynamic_cast<Ball*>(objects[i])->getdPdt();
现在,精明的 reader 会问的问题有所不同,但同样困难。为什么知道objects[i]
指向一个Ball
?为什么这些知识不以变量的类型编码?这就是 C++ 中的类型。回想一下,C++ 是一种静态类型语言。对此的任何例外(并且 dynamic_cast
自然是一个例外,其中包含“动态”一词)应该是非常合理的。如果有一些代码根据变量的类型决定做什么,那么该代码通常应该是基类 class.
最后,在 object-oriented 设计范例中,您只能做两件不同的事情。要么将 getdPdt
添加到 Object
,以便它可用于所有 Object
;或者将您的 Ball
放在一个单独的篮子中,篮子的类型表明里面有 Ball
,而不仅仅是 Object
。 dynamic_cast
是对 OO 范式的偏离。一个偏差是否可以接受由你决定,但如果你发现自己偏离它很多,那么也许你想考虑一个不同的范例。