【问题标题】:How do you return a pointer to a base class with a virtual function?如何使用虚函数返回指向基类的指针?
【发布时间】:2011-03-04 18:46:30
【问题描述】:

我有一个名为 Element 的基类,一个名为 Vector 的派生类,我正在尝试从 Vector 中的 Element 重新定义两个虚函数。

//element.h
template <class T>
class Element
{
public:
Element();

virtual Element& plus(const Element&);
virtual Element& minus(const Element&);
};

在另一个文件中

//Vector.h
#include "Element.h"

template <class T>
class Vector: public Element<T> {
T x, y, z;

public:

//constructors
Vector();
Vector(const T& x, const T& y = 0, const T& z =0);
Vector(const Vector& u);

...

//operations
Element<T>& plus(const Element<T>& v) const;
Element<T>& minus(const Element<T>& v) const;
... 

};

//sum
template <class T>
Element<T>& Vector<T>::plus(const Element<T>& v) const
{
Element<T>* ret = new Vector((x + v.x), (y + v.y), (z + v.z));
return *ret;
}

//difference
template <class T>
Element<T>& Vector<T>::minus(const Element<T>& v) const
{
Vector<T>* ret = new Vector((x - v.x), (y - v.y), (z - v.z));
return *ret;
}

但我总是得到

错误:“const class Element”没有名为“x”的成员

那么,我可以定义我的虚函数来代替 Vector& 作为参数,还是有办法让我通过指向 Element 的指针访问 Vector 的数据成员?

我对继承多态性还是很陌生,仅供参考。

编辑:尝试 static_cast(如下所示)并没有解决我的问题——或者我的语法错误。我以我能想象的两种方式尝试了静态转换,现在我的错误是 > error: 'const class Element' has no member named 'x'

我更新的代码是: //和 模板 元素&向量::plus(const Element& v) const { 元素* ret = static_cast*>(操作符 new((x + v.x), (y + v.y), (z + v.z))); 返回 *ret; }

//difference 
template <class T> 
Element<T>& Vector<T>::minus(const Element<T>& v) const 
{ 
Element<T>* ret = new Vector<T>(static_cast<Vector*>((x - v.x), (y - v.y), (z - v.z)));
return *ret; 
} 

我认为继承多态性的全部意义在于对派生类的引用实际上与对基类的引用相同。为什么我必须跳过这些圈子?

【问题讨论】:

  • getx 这个词没有出现在您的代码 sn-p 中。我认为你错过了一些东西。
  • 哎呀!在我发布时修复了代码 - 忘记更改错误消息。应该是:>错误:'const class Element'没有名为'x'的成员

标签: c++ inheritance templates virtual return


【解决方案1】:

编译器说的很明显:基类 Element 没有 有成员变量'x',因为 x 是在 Vector 中而不是在 Element 中声明的。 试试这个:

Element<T>& plus(const Element<T>& v) const     {
const Vector<T> & vect = dynamic_cast<const Vector<T> &>(v);
Vector<T>* ret = new Vector((x + vect.x), (y + vect.y), (z + vect.z));
return *ret;
}

请注意,如果您以这种方式返回指针,您可能会遇到任何内存泄漏问题。

【讨论】:

  • 如上所述,这可行,但会导致另一个问题。是的,我意识到存在内存泄漏,但你如何解决这个问题?我也在使用这段代码来重载 operator+,我知道你应该返回那些引用,这样你就可以链接操作符。动态分配内存允许我返回一个引用,但我不太确定何时或如何销毁创建的对象,或者是否有更好的方法来管理我的内存。有什么建议吗?
  • 删除对象的方法有很多:你可以像这样添加析构函数: void Vector::destroy() { delete this;当您不再需要该实例时调用此方法。这种解决方案很危险,因为您可以在堆栈分配的对象上调用 destroy() ,但可以。如果任何创建新对象的方法返回对象的指针而不是其引用会更好。
【解决方案2】:

我可以定义我的虚函数来代替 Vector& 作为参数

没有;参数类型必须相同,函数才能覆盖基类虚函数。

有没有办法让我通过指向 Element 的指针来访问 Vector 的数据成员?

可以,但您需要使用static_castdynamic_castElement&amp; 参数转换为Vector&amp;

如果您确定参数确实是Vector,则只能使用static_cast。当然,如果你知道这一点,那么你可以将参数的类型更改为Vector&amp;

如果您不确定自己是否确实拥有Vector,则可以使用dynamic_cast

const Vector<T>& w = dynamic_cast<const Vector<T>&>(v);

请注意,如果参数确实是 Vector,这将成功,否则将通过抛出 std::bad_cast 失败。您可以改为转换指针(取消引用并根据需要获取地址),在这种情况下,失败将导致转换返回 null 而不是引发异常。

也就是说,继承在这里很可能是错误的工作工具:尚不完全清楚您的实际用例是什么。

【讨论】:

  • 谢谢,这真的很有帮助——我会做一个静态演员。我正在做一个赋值程序,我认为我们应该将 plus 和 minus 定义为虚函数的唯一原因是让我们探索继承。我试图将 plus 和 minus 定义为纯虚函数,它们应该是,但是当我尝试构造 Vector 对象时这会导致灾难。感谢您的帮助!
  • 其实这并没有完全解决我的问题。我以我能想象的两种方式尝试了静态转换,现在我的错误是 > 错误:'const class Element' has no member named 'x' 我的代码是://sum template Element& Vector::plus(const Element& v) const { Element* ret = static_cast*>(operator new((x + vx), (y + vy), (z + vz)));返回 ret; } //差异模板 Element& Vector::minus(const Element& v) const { Element ret = new Vector(static_cast((x - vx), (y - vy), (z - vz)));返回 *ret; }
  • @Nick:您需要转换v 本身,而不是表达式的结果。我建议从The Definitive C++ Book Guide and List获得一本介绍性书籍
  • 这行得通,但它导致了另一个问题,我已在单独的帖子中发布*。谢谢! *stackoverflow.com/questions/3079980/…
猜你喜欢
  • 1970-01-01
  • 2021-06-25
  • 2013-04-10
  • 2010-11-03
  • 2020-07-22
  • 1970-01-01
  • 1970-01-01
  • 2020-12-27
  • 1970-01-01
相关资源
最近更新 更多