0

我在从直接父类 Base 类调用方法时遇到了挑战,但我可以轻松地调用 Base 类的父类中的方法。为了澄清我的意思是代码:

首先是opencascade库类的结构:

class TopoDS_Shape 
{
public:
   //..... a lot of methods like Closed(), Oriantable(), etc
};

class TopoDS_Face : public TopoDS_Shape
{
   TopoDS_Face(); // implementation is like TopoDS_Face::TopoDS_Face(){}
}

在我的代码中,有两种拓扑面平面(ModelFace 类)和非平面(ModelBend 类)。这两个面共享 MFace 类中定义的 6 个属性,但只有 ModelBend 类有自己的附加属性,所以我设计的系统如下

MFace类:

class MFace : public TopoDS_Face 
{
 FaceID mFaceID;
 PlaneType mPlaneType;
 FaceType mFaceType;
 gp_Pnt mFaceNormal;

 public:
  void ModelFace::extractEdges()
  {
    for (TopExp_Explorer edgeEx((*this), TopAbs_EDGE); edgeEx.More(); edgeEx.Next())
    {
      TopoDS_Edge edge = TopoDS::Edge(edgeEx.Current());
      ModelEdge edgex(edge);

      addEdge(edgex);
    }
  }

  // Setters and getters

  // The OpenCascade Lib has a non-template method similar to this for converting a  
  // TopoDS_Shape to a face/edge/vertex/wire
  template<typename T>
  static T& toFace(TopoDS_Face& shape)
  {
    return *(T*) &shape;
   }
};

模型面类:

 class ModelFace : public MFace
 {
   ModelFace(); // implementation is like ModelFace::ModelFace(){}

   void ModelFace::init(FaceID faceID) // WORKS LIKE A CHARM!!!
   { 
     setFaceId(faceID);

     std::cout << "ID : " << getFaceId() << '\n';

     if (Closed()) {
      std::cout << "Orr : " << Orientable() << '\n';
     }
   }

 };

模型弯曲类:

class ModelBend : public MFace
 {
   // Bend attributes : angles, radius, etc
   ModelBend(); // implementation is like ModelBend::ModelBend(){}

   // Setters and getters
   // methods for computations

};

用法:有一个模型类表示 CAD 模型并存储其所有拓扑 ModelFace/ModelBend 数据。该类以 TopoDS_Shape 的形式获取拓扑数据,并将其分类assignAttributes()如下所示:

  void Model::assignFaceAttributes(const FaceID faceID, TopoDS_Shape& aShape)
  {
    // TODO : set the face attributes
    TopoDS_Face pTopoDSFace = TopoDS::Face(aShape);
    Standard_Real curvature = computeCurvature(pTopoDSFace);

    if (curvature == 0.0){

      std::cout << "Face" << '\n';

      // Convert TopoDS_Face to ModelFace
      ModelFace& pModelFace = MFace::toFace<ModelFace>(pTopoDSFace);

      // This code work well : calls Orientable() in the TopoDS_Shape class
      std::cout << "Orientable? : " << pModelFace.Orientable() << '\n';

      // Works well
      pModelFace.init(faceID);

      // **PROGRAM CRASHES HERE!!!!!!!!!!!!!!**
      pModelFace.extractEdges();

      //...

    } else {
      // .....
      std::cout << "Bend" << '\n';

      // Convert TopoDS_Face to ModelBend
      ModelBend& pModelFace = MFace::toFace<ModelBend>(pTopoDSFace);

      //...
    }

    addFace(&pModelFace);

  }

当我运行程序时,它在调用pModelFace.extractEdges()in时崩溃,assignAttributes()但是当我将方法中的 for 循环复制extractEdges()init()方法中时,它工作正常。

我的 OOD/OOP 不是那么好。请您帮我解决问题以及这种行为的原因。提前致谢。

4

1 回答 1

1

这看起来与您自己的其他问题重复: Assigning a TopoDS_Face object to its child object compiles without errors but I have 3 valgrind errors

TopoDS_Shape没有虚拟方法(包括没有虚拟析构函数),并且在 OCCT中通过副本进行管理(例如,不是动态分配的)。像您一样添加类字段MFace只有在您完全存储对象时才会起作用MFace- 否则您只是将内存中的较小对象TopoDS_Shape转换为较大的对象,MFace从而导致读取/写入未初始化的内存并崩溃。

MFace你和之间的主要区别在于TopoDS_Face它没有TopoDS_Face定义新的类字段或虚拟方法,这允许别名TopoDS_Shape没有TopoDS_Face副作用。

例如:

void parseMFace (TopoDS_Shape& theFace)
{
  MFace* anMFace = (MFace* )&theFace;
  anMFace->doSomething();
}

int main()
{
  MFace anMFace;
  parseMFace (anMFace); // unsafe, but should work
  TopoDS_Face aTFace;
  parseMFace (aTFace); // will crash
  TopoDS_Compound aComp;
  BRep_Builder().MakeCompound (aComp);
  BRep_Builder().Add (aComp, anMFace); // here MFace will be truncated to TopoDS_Shape
  for (TopoDS_Iterator aFaceIter (aComp); aFaceIter.More(); aFaceIter.Next()
  {
    TopoDS_Face& aTFace2 = TopoDS::Face (aFaceIter.Value());
    parseMFace (aTFace2); // will crash, because TopoDS_Compound does not store MFace 
  }
  std::vector<MFace> anMFaces;
  anMFaces.push_back (anMFace);
  parseMFace (anMFaces[0]); // OK, but unsafe
}
于 2020-04-04T09:21:56.280 回答