C ++将类型A的变量分配给扩展A的类型B.

时间:2014-07-16 15:54:23

标签: c++

我尝试创建一个拼贴系统,用于创建拼贴的单个实例,并将拼贴添加到拼贴数组,允许您调用Tile::s_tileList[1]来获取污垢拼贴。

但是,我遇到了一些问题。这是完整的磁贴代码:

tile.h

#pragma once

class Tile {
public:
    static const Tile s_tileList[128]

    static const Tile s_dirt;

    Tile(int tileId);
    virtual ~Tile();
protected:
private:
    int m_tileId;
};

tile.cpp

#include "tile.h"

#include "tile_dirt.h"

const Tile Tile::s_dirt = TileDirt(1); // This line errors

Tile::Tile(int tileId) {
    s_tileList[tileId] = *this;
    m_tileId = tileId;
}

Tile::~Tile() {

}

tile_dirt.h

#pragma once

#include "tile.h"

class TileDirt : Tile {
public:
    TileDirt(int tileId);
    virtual ~TileDirt();
protected:
private:
};

当我尝试将s_dirt分配给TileDirt时,我收到以下错误:

conversion to inaccessible base class "Tile" is not allowed

我在这里做错了什么?

我尝试过:

static const Tile* s_dirt;

并指定它:

const Tile* Tile::s_dirt = new TileDirt(1);

但这只会增加另一个错误:no suitable constructor exists to convert from "const Tile *" to "Tile"

2 个答案:

答案 0 :(得分:3)

在C ++中,类型Foo的变量表示一个足以容纳Foo对象的内存块(基本上完全正确)。它正是Foo类型的数据。

如果您尝试在该内存中放入其他内容,您将获得从object slicing到未定义行为(这是不好的)的任何内容。

在许多其他语言(Java,C#,两个名称)中,类型Foo的变量实际上代表了其他地方Foo数据的句柄,或者可能是Foo的派生类。通常这些是垃圾收集的,这是一个非确定性系统,在运行时引擎确定它们名义上无法从用户代码中访问之后,您的对象将在未来的某个未知点被销毁。

要在C ++中模拟这个,你需要一个智能指针 - std::unique_ptr<Foo>std::shared_ptr<Foo>。这些在垃圾收集智能指针上并不完整,但除非您正在制作自引用数据,否则它们通常都足够好。在C ++中你必须考虑的一件事是“谁拥有这些数据的生命周期”。

std::shared_ptr通常最容易使用。

Tile个实例替换为std::shared_ptr<Tile>,将new Tile(blah)的号码替换为std::make_shared<Tile>(blah)

接下来,默认情况下,C ++中的class继承是私有的 - 除了您自己类型的实例之外,没有人知道您是父类的子级。如果您想要公共继承,请使用public Tile

您希望让Tile构造函数将自身的副本存储在静态数组中是不好的。不要在构造函数中做那种事情,让它在构造函数之外完成。 (生成一个指向这个的共享指针有点烦人:最简单的方法实际上效果不好)

答案 1 :(得分:0)

错误与您问题的标题不符。

const Tile Tile::s_dirt = TileDirt(1); // This line errors

您正在声明一个全局常量(不是宏常量,而是内存分配常量,类似于全局变量)。

如何在“主要”功能上进行测试,放弃全局内容,以及常量,首先:

int main(...)
{
  Tile* MyTyle = new TileDirt();
}

然后,如果确实需要,请更改为全局成员,以及常量成员?