【发布时间】:2017-10-25 22:44:44
【问题描述】:
让函数将指向基类型的指针转换为指向派生类型的指针的最佳方法是什么?为什么以下不自动工作?
#include <iostream>
#include <memory>
#include <queue>
class Base{
public:
Base() {};
};
class Derived : public Base{
public:
Derived() : Base() {};
};
void foo(const std::shared_ptr<Derived>& dp){ // "wrong" signature
std::cout << "it runs\n";
}
int main(int argc, char **argv)
{
std::queue<std::shared_ptr<Base>> q;
q.push( std::make_shared<Derived>() );
foo(q.front()); // error
return 0;
}
用以下作品替换foo。但是,这可能不会强制将参数强制为 Derived 类,这是我正在编写的程序中唯一应该存在的东西。
void foo(const std::shared_ptr<Base>& dp){
std::cout << "it runs\n";
}
我也可以手动投射指针。还有其他想法吗?
编辑:
一些人建议我使用虚函数。我想他们的意思是我应该把foo 作为一个虚拟函数放在类中,如下所示。但是,如果我错了,请纠正我的理解。
#include <iostream>
#include <memory>
#include <queue>
class Base{
public:
Base() {};
virtual void foo () { std:: cout << "base\n"; };
};
class Derived : public Base{
public:
Derived() : Base() {};
void foo() {std::cout << "derived\n";};
};
int main(int argc, char **argv)
{
std::queue<std::shared_ptr<Base>> q;
q.push( std::make_shared<Derived>() );
q.front()->foo();
return 0;
}
编辑 2: 谢谢大家的帮助。目前我已经接受了一个答案,但在我的实际程序中,我可能会倾向于使用@alain 的铸造答案,实际上。在这个程序中,我的队列充满了我一次弹出一个的事件。除了这个队列,我还有多个事件处理程序——根据它是什么类型的派生类,我将使用不同的事件处理程序函数。所以我认为这些事件拥有事件处理函数没有多大意义。实际上,这让我觉得我需要重新考虑在事件中完全继承。如果有一些队列允许不同类型的对象,我根本不会遇到这个问题。不过,也许由于其他原因这很糟糕,我不确定。
【问题讨论】:
-
记住:所有
Derived都是Base,但并非所有Base都是Derived。 -
“最好”的方式是使用
virtual函数。 -
当你不想共享所有权时,不要使用 shared_ptr 作为函数参数。
-
@Taylor 你几乎把它钉在那里。您唯一缺少的想法是
Base的虚拟析构函数。在删除Base时,需要虚拟析构函数以允许系统追踪并销毁正确的对象。忽略这一点会导致可怕的未定义行为,其中可能会发生许多神奇的事情,从看起来可以工作的程序到组建机器大军并消灭地球上所有有机生命的程序。 -
我明白你的困惑。我的第一条评论是为了回应 Taylor 开始尝试
virtual并询问他们是否有任何问题的编辑。
标签: c++ pointers shared-ptr