【问题标题】:to downcast elements from parent class从父类向下转换元素
【发布时间】:2016-03-14 07:07:21
【问题描述】:

我正在用 OpenGL 做计算机作业

但我是 C++ 新手。这与 Java 非常不同。

我试过了。

class Map {
private :
public :
    short mapkind;
    float a = 5;
    Map() 
    {}

};

class Road : public Map {
private :
public :    
    Road()
    {
        mapkind = 0;
    }
};

class Glass : public Map {
private:
public:
    float color[3] = { 0.0, 1.0, 0.0};

    Glass()
    {
        mapkind = 1;
    }
};

然后我制作了数组。

Map* maps[10] = { new Road(),
   new Glass(), 
   new Road(), 
   new Glass(), 
   new Glass(), 
   new Road(), 
   new Road(), 
   new Glass(), 
   new Road(), 
   new Glass() };

这是在我的主循环中。

for (int i = 0; i < 10; i++) {
if ((*maps)[i].mapkind == 0) {
    //draw road
    Road* temp;
    temp = (Road*)maps[i];
}
else if ((*maps)[i].mapkind == 1) {
    //draw glass
    Glass* temp;
    temp = (Glass*)maps[i];
}
else {
    //exit(4);
    printf("error %hd %d \n", (*maps)[i].mapkind);
}
}

我学过 C 和指针,但它太老了。我猜在 Array 中,将 'new Class()' 作为一个元素是错误的,但我不知道如何解决。

第一个数字是短类型 %hd,第二个是 int 类型 %d,用于打印短类型变量 'mapkind'

【问题讨论】:

  • 不要用成员变量来说明它是什么类型的对象,而是学习虚函数
  • 如果您通过添加virtual 方法(或析构函数)使您的类具有多态性,那么您可以简单地使用dynamic_cast 来检查基类是否指向特定的派生类.例如,检查maps[i] 是否指向Glass 或不使用Glass* temp = dynamic_cast&lt;Glass*&gt;(maps[i])。请注意,这仅在类是多态的(具有虚拟方法)时才有效。

标签: c++ arrays oop pointers downcast


【解决方案1】:

这里的问题不是转换,而是你如何取消引用数组:

(*maps)[i].mapkind

这首先取消引用maps(它给你maps[0]),然后你将该指针用作数组,但事实并非如此。这会导致未定义的行为

改为使用maps[i]-&gt;mapkind(或者如果您想使用显式取消引用和点语法(*(maps[i])).mapkind)。


此外,在使用 C++ 编程时,您应该“忘记”C 风格的转换,它可能会在您最意想不到的时候导致麻烦。而是使用例如static_cast:

Glass* temp = static_cast<Glass*>(maps[i]);

或者就像我在评论中提到的那样,使用 虚拟函数,它将使用正确的类在正确的对象中调用。

【讨论】:

  • 谢谢。我试过这个,它有效。但是我有分段错误,所以我会解决它。
【解决方案2】:

除了已经讨论过的事情之外,我认为如果您“通常”必须将对象从基类转换为派生类,那么您做错了什么。是的,您可能在整个程序中这样做了几次,但规则应该是您的类中有一个方法可以为您完成工作,并且不要将其强制转换为派生类来执行该操作任务。所以,如果你想绘制你的对象,你有一个Draw 函数:

class Map {
private :
public :
    short mapkind;
    float a = 5;
    Map() 
    {}
    virtual void Draw() = 0;
};

然后为RoadGlass等实现这个函数

我说“你有时可能会强制转换”的原因是,假设你有 30-40 个从 Map 派生的不同对象,你需要对 Aeroplane 做一些特别的事情,这只会在少数地方发生,然后使用 cast it 然后做东西是合理的。我的编译器项目使用llvm::dyn_cast作为“如果这个对象是这种类型,那么需要做一些特殊的事情”的方法。

【讨论】:

  • 谢谢。我知道这不是好的设计。但我需要可以包含两个或多个类对象的数组。您说添加绘图功能会很好,我会将其应用于我的代码。但是我需要研究一下什么是虚函数。
  • 虚函数的全部意义在于它们可以放在基类中,你可以拥有一个基类的数组[或向量],然后用它来调用一个函数在派生类中定义。
【解决方案3】:

.你的基类应该至少包含一个虚函数,即使如此,你也必须添加虚析构函数,即:

class Map {
    short mapkind;
    float a;
public :        
    Map() : a(5.0f)
    {}
    virtual ~Map(){}
    virtual short getMapkind() const { return mapkind; }
};

在派生类中重写 getMapkind 函数。 那么你可以使用这样的东西:

vector<Map*> vec;
vec.push_back(new Road());
auto mk = vec.back()->getMapkind();

【讨论】:

  • 根本没有真正解释根本问题,是吗?
  • 展示了如何获取 mapkind 的正确方法,然后您可以使用 C 样式转换、static_cast、dynamic_cast(使用 RTTI),甚至 reinterpret_cast - 一切都会正常工作。
  • 除了ORIGINAL的问题不是那个,就是间接的地方放错了。使用函数获取 mapkind 的原始代码仍然会越界访问,并且仍然是未定义的。它没有帮助,即使它是一个更整洁的设计。至少如果您要提出更改建议,请确保他们正在解决 OP 提出的问题 - 或者非常清楚您没有回答原始问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 1970-01-01
  • 2020-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-12-23
  • 2015-02-13
相关资源
最近更新 更多