从父 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;
};
然后为Road
、Glass
等实现此功能
我说 "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" 的方法。
我正在用 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;
};
然后为Road
、Glass
等实现此功能
我说 "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" 的方法。