从父 class 向下转换元素

to downcast elements from parent class

我正在用 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和指针,但是太老了。我想在数组中,将 'new Class()' 作为一个元素是错误的,但我不知道如何解决它。

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

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

(*maps)[i].mapkind

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

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


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

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

或者像我在评论中提到的那样,使用 虚函数 ,它将使用正确的 class.

在正确的对象中调用

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

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

覆盖派生的 classes 中的 getMapkind 函数。 那么你可以使用这样的东西:

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

除了已经讨论过的事情之外,我认为如果你必须将你的对象从基础 class 转换为派生的 class "as a rule",你正在做有事吗。是的,您可能会在整个程序中多次这样做,但规则应该是您在 class 中有一个方法可以为您完成工作,并且不要将其强制转换为派生class 执行该任务。所以,如果你想绘制你的对象,你有一个 Draw 函数:

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

然后为RoadGlass等实现此功能

我说 "you may sometimes cast" 的原因是,假设你有 30-40 个不同的对象从 Map 派生,你需要对 Aeroplane 做一些特殊的事情,这只发生在几个地方,然后使用 cast it 然后 do stuff 是合理的。我的编译器项目使用 llvm::dyn_cast 作为 "if this object is this type, then special things need to be done" 的方法。