[英]why can't I cast a pointer to Derived class member function to the same but of class Base?
[英]Why doesn't the function cast a pointer correctly (from base class to derived class)
使函数将指针转换为基本类型的指针,或将指针转换为派生类型的最佳方法是什么? 为什么以下自动无法工作?
#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的强制转换答案。 在此程序中,我的队列中充满了每次弹出一个事件。 除了该队列之外,我还有多个事件处理程序-根据派生类的类型,我将使用其他事件处理程序的功能。 因此,考虑这些事件具有事件处理程序功能对我来说没有多大意义。 实际上,这使我认为我需要重新考虑在事件中完全继承。 如果有一些队列允许不同类型的对象,我将根本不会遇到这个问题。 不过,由于其他原因,这可能很糟糕,我不确定。
需要进行两项更改:
通过向Base
类添加virtual
函数来启用多态。 最好有一个虚拟析构函数,所以
virtual ~Base() {};
然后,无法将std::shared_ptr<Base>
自动转换为std::shared_ptr<Derived>
。 您必须使用dynamic_pointer_cast
:
foo(dynamic_pointer_cast<Derived>(q.front())); // error
还请检查是否确实需要这样做,因为通常不需要从基础到派生的强制转换的设计会更好。
std::queue<std::shared_ptr<Base>> q;
是指向Base
的(共享)指针的队列,因此
q.front()
将返回一个std::shared_ptr<Base>
。
void foo(const std::shared_ptr<Derived>& dp)
需要std::shared_ptr<Derived>
虽然Base
和Derived
之间存在关系,但是std::shared_ptr<Base>
和std::shared_ptr<Derived>
之间没有关系。 它们是shared_ptr
两种不同类型。
“好吧,”您可能会想,“我只是shared_ptr::get
指针拿出来。赢了!” 您可以认为,但是...不。 Derived
是Base
,但Base
不是Derived
。
此时,您有两种选择:将Base
转换为Derived
因为您知道当当是它是Derived
,但这仅在玩具代码中才真正可行,因为您确实知道它是Derived
。 实际代码变得更加混乱。 这是一个坏主意。
因此,让我们跳过这个好主意吧? 虚拟功能。
#include <iostream>
#include <memory>
#include <queue>
class Base
{
public:
// none of the constructors do anything, so I got rid of them.
// code that's not there has no bugs.
virtual ~Base() = default; // must provide virtual destructor so that
// correct destructors get called when a Base
// is destroyed
virtual void foo() = 0; // pure virtual function. All descendants must
// provide this function
// Pure virtual has the side effect of making
// it impossible to instantiate a Base.
// This may or may not be what you want. If it
// isn't, remove the =0 and implement the function.
/*
virtual void foo()
{
std::cout << "I pity the foo who derives from Base.\n"
}
*/
};
class Derived: public Base
{
public:
void foo() // implement Base::foo
{
std::cout << "it runs\n";
}
};
int main()
{
std::queue<std::shared_ptr<Base>> q;
q.push(std::make_shared<Derived>());
q.front()->foo();
return 0;
}
您需要在基类中有一个虚函数 ,否则它将把它视为继承而不是多态,因此它不会用基类指针引用子对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.