C++派生类的reinterpret_cast

发布于 2024-10-13 00:20:03 字数 1207 浏览 7 评论 0 原文

父类:

template <class T>
class Point
{
    protected

        T x;
        T y;

};

派生类:

template <class T>
class Point3DTopo: public Point <T>
{
    protected:

        T z;
        Face <T> *face;   //Points to any face
};

我想将 PointsList 类的一个对象转换为另一个对象 Points3DTopoList(反之亦然) 其中:

template <class T>
class PointsList
{
  protected:
         std::vector <Point <T> *> points;  //Only illustration, not possible with   templaes
};


template <class T>
class Points3DTopoList
{
  protected:
         std::vector <Point3DTopo <T> *> points;  //Only illustration, not possible with   templaes
};

是否允许这种转换?

Points3DTopoList <T> *pl = new Points3DTopoList <T> ();
...
PointsList <T> *pl = reinterpret_cast < PointsList <T> * > ( pl3D );

那么反向转换呢?

PointsTopoList <T> *pl = new PointsTopoList <T> ();
...
Points3DTopoList <T> *pl3D = reinterpret_cast < Points3DTopoList <T> * > ( pl );

每个Point3Topo的Face指针将被初始化为NULL还是未定义?

Parent class:

template <class T>
class Point
{
    protected

        T x;
        T y;

};

Derived class:

template <class T>
class Point3DTopo: public Point <T>
{
    protected:

        T z;
        Face <T> *face;   //Points to any face
};

I would like to cast one object of the class PointsList to another object Points3DTopoList (and vice versa) where:

template <class T>
class PointsList
{
  protected:
         std::vector <Point <T> *> points;  //Only illustration, not possible with   templaes
};


template <class T>
class Points3DTopoList
{
  protected:
         std::vector <Point3DTopo <T> *> points;  //Only illustration, not possible with   templaes
};

Is such conversion allowed?

Points3DTopoList <T> *pl = new Points3DTopoList <T> ();
...
PointsList <T> *pl = reinterpret_cast < PointsList <T> * > ( pl3D );

And the reverse conversion?

PointsTopoList <T> *pl = new PointsTopoList <T> ();
...
Points3DTopoList <T> *pl3D = reinterpret_cast < Points3DTopoList <T> * > ( pl );

A Face pointer of each Point3Topo will be initialized to NULL or will be undefined?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

黑凤梨 2024-10-20 00:20:03

这样的演员阵容是不允许的。这是一个基本问题:您要么必须通过复制进行转换,要么调整您的类定义,以便您拥有一个 ListOf,即对点类型和内部类型进行参数化观点。

但是,无论如何,类设计都是有缺陷的:您不应该从 Point 派生 Point3D,这违反了 里氏替换原理 (LSP) – 或者更一般地说:3D 点不是 2D 点。事实上,恰恰相反:2D 点是 3D 点的特例。

所以如果你想在这里继承,它应该走另一种方式(即2D从3D继承),但这很可能违反LSP,并且非常尴尬(从那时起,您的 2D 点将具有始终固定的冗余变量)。简单地说,2D和3D点之间不存在合适的继承关系,它们是不同的实体。

Such a cast isn’t allowed. This is a fundamental problem: you either have to convert via copying, or adapt your class definitions so that you have a ListOf<PointT, T>, i.e. parametrized both on the point type and the type inside the point.

However, the class design is flawed anyway: you should not derive Point3D from Point, this violates the Liskov substitution principle (LSP) – or more generally: a 3D point is not a 2D point. Quite the opposite, in fact: a 2D point is a special case of the 3D point.

So if you want to have an inheritance here, it should go the other way (i.e. 2D inherits from 3D) but this would most likely also violate LSP, and is very awkward (since then your 2D point would have a redundant variable that’s always fixed). Simply put, there is no suitable inheritance relation between 2D and 3D points, they are distinct entities.

巷雨优美回忆 2024-10-20 00:20:03

reinterpret_cast 唯一保证的是从 A* 到 B* 然后再返回到 A* 会产生原始指针。除了转换回 A* 之外,使用中间 B* 进行任何操作都是未定义的。

Just about the only thing reinterpret_cast guarantees is that casting from A* to B* then back to A* yields the original pointer. Using the intermediate B* for anything other than casting back to A* is undefined.

东风软 2024-10-20 00:20:03

这只是双向的未定义行为。

It's just Undefined Behavior both ways.

ま昔日黯然 2024-10-20 00:20:03

鉴于 Point3DTopo 是从 Point 派生的,因此提供从 Points3DTopoList 到 PointsList 的转换可能是明智的。继承可以自动提供转换,但我怀疑您的公共接口要求(从问题中省略)使其比资产更麻烦。

提供转化路径的示例:

template<class T>
struct PointsList {
  // Points3DTopoList needs a way to construct a PointsList
  template<class Iter>
  PointsList(Iter begin, Iter end)
  : points(begin, end)
  {}

private:
  std::vector<Point<T> > points;
};

template<class T>
struct Points3DTopoList {

  operator PointsList<T>() const {
    return PointsList<T>(points.begin(), points.end());
  }

  PointsList<T> to_points_list() const {
    return PointsList<T>(points.begin(), points.end());
  }

private:
  std::vector<Point3DTopo<T> > points;
};

这提供了两个转化路径 - 通常您会选择一个而不提供另一个。转换运算符是隐式转换(在 C++0x 中,您可以将其标记为显式),而命名方法在技术术语中不是“转换”(因此从不适用于任何隐式或显式转换),而是显式调用并以这种方式使用。

您还可以在 PointsList 中使用接受 Points3DTopoList 的显式构造函数提供显式转换,这在当前的 C++ 中有效,但代价是颠倒了通常的依赖关系:也就是说,PointsList 会知道并关心 Points3DTopoList反之亦然。

但是,您提供一个“generic-Point”容器可能更有意义;也就是说,它接受任何具体的 Point-like 类型。

template<class Point>
struct GenericPointContainer {
private:
  std::vector<Point> points;
};

这里最大的优势是 GenericPointContainer 的方法可以使用 Point 派生类的各种功能,这些功能不存在于 Point 本身中,但仍然可以直接在 Point 上实例化。这是有效的,因为实例化类模板时,所有方法都不会被实例化,一个实际的例子是 std::reverse_iterator 如何重载operator+=,它只适用于随机访问迭代器,但可以在非随机访问迭代器上实例化,例如 std::reverse_iterator::iterator> 。

然后,各种列表类可能会变成简单的 typedef,如果它们仍然需要的话:

typedef GenericPointContainer<Point<int> > PointsList;
typedef GenericPointContainer<Point3DTopoList<int> > Points3DTopoList;

C++0x 确实可以帮助您使用模板 typedef(您可以在当前的 C++ 中使用重新绑定,但这会变得迟钝);正如您所看到的,我必须为 typedef 指定 T,因此它并不像其他情况那样通用。

It could be sensible to provide a conversion from Points3DTopoList to PointsList given that Point3DTopo is derived from Point. Inheritance, which provides that conversion automatically, is a possibility, but I suspect your public interface requirements (omitted from the question) make it more of a hassle than an asset.

Example of providing a conversion path:

template<class T>
struct PointsList {
  // Points3DTopoList needs a way to construct a PointsList
  template<class Iter>
  PointsList(Iter begin, Iter end)
  : points(begin, end)
  {}

private:
  std::vector<Point<T> > points;
};

template<class T>
struct Points3DTopoList {

  operator PointsList<T>() const {
    return PointsList<T>(points.begin(), points.end());
  }

  PointsList<T> to_points_list() const {
    return PointsList<T>(points.begin(), points.end());
  }

private:
  std::vector<Point3DTopo<T> > points;
};

This provides two conversion paths – normally you'd pick one and not provide the other. The conversion operator is an implicit conversion (in C++0x you can mark it explicit), while the named method isn't a "conversion" in technical terms (thus never applies for any implicit or explicit conversion), but is explicitly called and used that way.

You can also provide an explicit conversion with an explicit constructor in PointsList which accepts a Points3DTopoList, and this works in current C++ at the expense of inverting the dependency relationship from how it would normally lie: that is, PointsList would know and care about Points3DTopoList instead of the other way around.

However, it may make more sense for you provide a "generic-Point" container; that is, one which accepts any concrete Point-like type.

template<class Point>
struct GenericPointContainer {
private:
  std::vector<Point> points;
};

The biggest strength here is methods of GenericPointContainer can use various features from derived classes of Point which aren't present in Point itself, yet still be instantiated on Point directly. This works because all methods aren't instantiated when a class template is instantiated, and a practical example is how std::reverse_iterator overloads operator+=, which only works for random access iterators, yet can be instantiated on non-random-access iterators, such as std::reverse_iterator<std::list<int>::iterator>.

Then various list classes may become simple typedefs, if they are even still required:

typedef GenericPointContainer<Point<int> > PointsList;
typedef GenericPointContainer<Point3DTopoList<int> > Points3DTopoList;

C++0x would really help you here with template typedefs (you could use a rebind in current C++, but that gets obtuse); as you can see I had to specify T for the typedefs, so it's not quite as general as otherwise.

爱人如己 2024-10-20 00:20:03

我已经得到了回答: C++ 重新解释转换?

而且它不会慢,因为只有指针将被复制。

您自己的演员阵容。

I was answered already: C++ reinterpret cast?

And it's will be not slow, because only the poiners will be copied.

YOUR OWN CAST FUNCTION.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文