将子类存储在超类向量中

Storing subclasses in superclass vector

本文关键字:向量 超类 子类 存储      更新时间:2023-10-16

我正在尝试为偶发噪声库构建一个序列器,用户可以在其中生成一个描述各种类型噪声层的XML文件,并获得结果。我很难理解继承在C++中是如何工作的。

不幸的是,并不是所有子类的方法(在本例中为CImplicitSphere)都是在超类(CImplicitModuleBase。这就是我目前所掌握的:

std::vector<anl::CImplicitModuleBase *> layers;
anl::CImplicitSphere tmp;
tmp.setCenter(0.0,0.0,0.0,0.0,0.0,0.0);
layers.push_back(&tmp);
value = layers.back()->get(0.0,0.0,0.0);

但我遇到了一个"纯虚拟方法"错误——这就是我陷入困境的地方——我需要键入cast吗?对此有一些讨论,但似乎表明这是个坏主意。

有没有更好的方法来构建我的代码,这样我就可以直接在层向量中初始化CImplicitSphere,并在进行时指向子类方法?

完整来源:

void ScalarTerrain::setupAccidentalNoise() {
printf("Making an array of noise functionsn");
std::vector<anl::CImplicitModuleBase *> layers;
try {
    printf("Getting data for next layern");
    pugi::xml_node layer = terrainData.child("layer");
    if(strcmp(layer.attribute("type").value(), "sphere") == 0) {
        printf("Layer is a sphere building a temp layern");
        anl::CImplicitSphere tmp;
        tmp.setCenter(
            layer.child("center").attribute("x").as_double(),
            layer.child("center").attribute("y").as_double(),
            layer.child("center").attribute("z").as_double(),
            layer.child("center").attribute("u").as_double(),
            layer.child("center").attribute("v").as_double(),
            layer.child("center").attribute("w").as_double()
        );
        layers.push_back(&tmp);
    }
     else {
        printf("Layer type not foundn");
    }

} catch (char * exception) {
    printf("Exception raised: %sn", exception);
}
try {
    for(int z = 0; z < z_chunk; z++) {
        for(int y = 0; y < y_chunk; y++) {
            for(int x = 0; x < x_chunk; x++) {
                value = layers.back()->get(
                    (double) x/x_chunk * 2, 
                    (double) y/y_chunk * 2, 
                    (double) z/z_chunk * 2
                );
                tc.values[x][y][z] = value;
                if(value < -0.5) tc.materials[x][y][z] = 0;
                else if (value < 0) tc.materials[x][y][z] = 1;
                else if (value < 0.5) tc.materials[x][y][z] = 2;
                else tc.materials[x][y][z] = 3;
            }
        }
    }
} catch (char * exception) {
    printf("Exception raised: %sn", exception);
}
}

这似乎有效,而且并不难看:

void ScalarTerrain::setupAccidentalNoise() {
printf("Making an array of noise functionsn");
std::vector<anl::CImplicitModuleBase *> layers;
anl::CImplicitModuleBase * tmp;

//anl::CImplicitSphere thisLayer;
try {
    printf("Getting data for next layern");
    pugi::xml_node layer = terrainData.child("layer");
    if(strcmp(layer.attribute("type").value(), "sphere") == 0) {
        printf("Layer is a sphere building a temp layern");
        tmp = new anl::CImplicitSphere();
        dynamic_cast<anl::CImplicitSphere*>(tmp)->setCenter(
            layer.child("center").attribute("x").as_double(),
            layer.child("center").attribute("y").as_double(),
            layer.child("center").attribute("z").as_double(),
            layer.child("center").attribute("u").as_double(),
            layer.child("center").attribute("v").as_double(),
            layer.child("center").attribute("w").as_double()
        );
        layers.push_back(tmp);
    }
     else {
        printf("Layer type not foundn");
    }

} catch (char * exception) {
    printf("Exception raised: %sn", exception);
}
try {
    printf("Iterating through blocksn");
    for(int z = 0; z < z_chunk; z++) {
        for(int y = 0; y < y_chunk; y++) {
            for(int x = 0; x < x_chunk; x++) {
                printf("getting block value at %d %d %dn",x,y,z);
                value = layers.back()->get(
                    (double) x/x_chunk * 2, 
                    (double) y/y_chunk * 2, 
                    (double) z/z_chunk * 2
                );
                tc.values[x][y][z] = value;
                if(value < -0.5) tc.materials[x][y][z] = 0;
                else if (value < 0) tc.materials[x][y][z] = 1;
                else if (value < 0.5) tc.materials[x][y][z] = 2;
                else tc.materials[x][y][z] = 3;
            }
        }
    }
} catch (char * exception) {
    printf("Exception raised: %sn", exception);
}
}

这是"正确"的做事方式吗?还是我偏离了目标?