为什么函数不能正确转换指针(从基 class 到派生 class)
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
。然而,这可能不会将参数强制为派生 class,这是我正在编写的程序中唯一应该存在的东西。
void foo(const std::shared_ptr<Base>& dp){
std::cout << "it runs\n";
}
我可能还可以手动投射指针。还有其他想法吗?
编辑:
一些人建议我使用虚函数。我想他们的意思是我应该把 foo
作为虚函数放在 class 中,如下所示。不过,如果我说错了,请指正我的理解。
#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 的铸造答案。在这个程序中,我的队列中充满了我一次弹出一个事件。除了这个队列之外,我还有多个事件处理程序——根据派生 class 的类型,我将使用不同的事件处理程序函数。因此,考虑这些事件拥有事件处理程序功能对我来说没有多大意义。实际上,这让我觉得我需要重新考虑在事件中完全继承。如果有一些队列允许不同类型的对象,我根本不会有这个问题。不过,也许由于其他原因这很糟糕,我不确定。
您的 Base class 中需要有一个 Virtual Function 否则它将被视为 Inheritance 而不是 Polymorphism 所以它不会用基 class 指针引用你的子对象。
需要进行两项更改:
通过将 virtual
函数添加到 Base
class 来启用多态性。有一个虚拟析构函数是个好主意,所以
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()
将return一个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
.
"Well then," 你可能会这么想,"I will just shared_ptr::get
the pointer out. Winning!" 你可能会这么想,但是……不。 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;
}
让函数将指针转换为基类型指针或派生类型指针的最佳方法是什么?为什么以下不自动工作?
#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
。然而,这可能不会将参数强制为派生 class,这是我正在编写的程序中唯一应该存在的东西。
void foo(const std::shared_ptr<Base>& dp){
std::cout << "it runs\n";
}
我可能还可以手动投射指针。还有其他想法吗?
编辑:
一些人建议我使用虚函数。我想他们的意思是我应该把 foo
作为虚函数放在 class 中,如下所示。不过,如果我说错了,请指正我的理解。
#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 的铸造答案。在这个程序中,我的队列中充满了我一次弹出一个事件。除了这个队列之外,我还有多个事件处理程序——根据派生 class 的类型,我将使用不同的事件处理程序函数。因此,考虑这些事件拥有事件处理程序功能对我来说没有多大意义。实际上,这让我觉得我需要重新考虑在事件中完全继承。如果有一些队列允许不同类型的对象,我根本不会有这个问题。不过,也许由于其他原因这很糟糕,我不确定。
您的 Base class 中需要有一个 Virtual Function 否则它将被视为 Inheritance 而不是 Polymorphism 所以它不会用基 class 指针引用你的子对象。
需要进行两项更改:
通过将 virtual
函数添加到 Base
class 来启用多态性。有一个虚拟析构函数是个好主意,所以
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()
将return一个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
.
"Well then," 你可能会这么想,"I will just shared_ptr::get
the pointer out. Winning!" 你可能会这么想,但是……不。 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;
}