【问题标题】:C++ reinterpret cast?C++ reinterpret_cast?
【发布时间】:2011-06-10 02:34:40
【问题描述】:

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

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

和

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

Point 和 Point3D 之间没有任何关系(继承或组合)...

template <class T>
class Point
{
    protected:

            T x;
            T y;

    public:
            Point( const T &x_, const T &y_ ) : x ( x_ ), y ( y_ ) {}
            inline T getX() const {return x;}
            inline T getY() const {return y;}
            inline void setX ( const T &x_ ) {x = x_;}
            inline void setY ( const T &y_ ) {y = y_;}
            ....
};

template <class T>
class Point3D
{
    protected:

            T x;
            T y;
            T z;
};

您对转化有何看法

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

其中 pl3D 表示指向 Points3DList 对象的指针。在这种情况下可以使用 reinterpret_cast 还是创建转换函数更好?这种情况下的数据模型是不能改变的……

【问题讨论】:

  • 这是个糟糕的主意,不要这样做。但是,如果没有 Point 和 Point3D 的定义,很难证明你应该做什么。另外,为什么在向量中存储指向值的指针而不是值本身?
  • 关于Point 和Point3D 类的信息还不够。如果我想转换它们,我需要能够设置它们包含的值。您所展示的只是四个只有受保护成员的类(我如何直接使用它们?)。
  • 我假设Point 真的是Point2DCartesian。顺便说一句,您在类定义中定义的成员隐式为inline,您对那里的关键字的使用是多余的。
  • @GMan。这是一个错误,我纠正了它......
  • 这仍然是一个错误,因为你有 Point 和一个假定的构造函数 Point2D;其中之一是不正确的。无论如何,我能再问一次你为什么这么多使用指针吗?

标签: c++ reinterpret-cast


【解决方案1】:

这里的行为将是完全未定义的。不要这样做!

【讨论】:

  • 从技术上讲,它是实现定义的(除了一些简单的情况)。
  • @GMan:即使在非 POD 的情况下? (比如OP的包含向量的类?)
  • @Oli:嗯,演员是在指针上完成的,谁是“映射是实现定义的”。 (§5.2.10/3)也就是说,我认为很明显实现定义的结果是“崩溃”。
  • 问题出在 STL 的向量中。在不复制整个向量的情况下缺少转换。如果存储类型的大小具有相同的大小,则可以进行强制转换。这是因为指向结构的指针具有相同的大小。 std::vector *> 和 std::vector *> 的实现可能具有相同的实现,但这是定义的实现。所以做一个重新解释演员可能会奏效,但由于它是未定义的,你不应该这样做。
  • @lionbest:有什么方法可以在不创建新对象的情况下投射 PontsList Points3DList?
【解决方案2】:

您必须编写自己的强制转换函数(构造函数或友元函数)。

类似:

template <class T>
class PointsList
{
    PointsList(Points3DList& p3d) : x(p3d->x), y(p3d->y) {};
... 

并使用:

PointsList <T> *pl = new PointList( pl3D );

【讨论】:

  • 但是 reinterpret_cast 非常危险。在这种情况下,您需要一个包装器。
  • @Ian:不要指望这会很慢。今天的编译器非常聪明。目前我正在使用一个等效的代码,它几乎完成了 SVGreg 的建议(但不要使用指针!new is 很慢!)。现在出乎意料:编译器不进行复制!它完全优化了副本,剩下的只是可以直接操作的整数值。
  • @Ian:速度不是您最关心的问题,而是您最后关心的问题。您主要关心的是一个有效的、正确的、可维护的程序。请注意,速度不是一个因素。事实上,如果你做对了,速度就会自动到来。永远不要为速度而编码,为正确而编码。
  • @Ian:首先,Konrad 和 GMan 说过的话;其次,过早的优化是万恶之源(D. Knuth)——担心发现它确实很慢之后会很慢;第三,如果你发现它确实很慢,你应该编写自己的写时复制优化或类似的东西(这可能很棘手而且很危险)。
  • 在两个类中对内部向量使用 boost 共享指针。这样就不需要复制向量了。
【解决方案3】:
PointsList <T> *pl = reinterpret_cast < PointList <T> * > ( pl3D );

这没有意义。大错特错。你只会从这样的演员中得到垃圾!

你甚至期望reinterpret_cast 解释Point 和Point3D 以使转换成功?

【讨论】:

    猜你喜欢
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-25
    • 2011-06-10
    相关资源
    最近更新 更多