C ++保持抽象类型的引用/指针

时间:2013-03-31 15:55:04

标签: c++

我是c +的新手,这个问题可能看起来很无趣,因为我只是更多的Java / Actionscript3而且我以前从未处理过与内存相关的事情。

无论如何我的问题是: 场景是一个抽象类(所以我可以从它派生并有多个场景,如MainScene等')

我想要SceneManager要做的是有一个指向选定场景的指针/参考(curSc) 然后我就像这样设置场景:setScene(& someScene)

但据我所知,要有一个指针,我还必须像这样初始化它: curSc =新场景; 但它不会让我这样做,因为Scene是一个抽象类......

class Scene {

public:
    Scene(void){}
    virtual ~Scene(void){}
    virtual void update() = 0;
    virtual void render() = 0;
};


class SceneManager {

public:
    SceneManager(void);
    ~SceneManager(void);
    void setScene(Scene *sc);
    Scene* curSc;
}

到目前为止,在我看来,在这种情况下使用指针是错误的,它将无法工作.. 但我很想知道如何实现我在这里尝试获得的功能

非常感谢

按要求修改 这就是我尝试使用它的方式:

首先,我有一个名为GameScene的派生类,它在这里:

class GameScene : public Scene 
{
public:
    GameScene(void);
    void render();
    void update();
}

在我的main()函数中:

GameScene gamescene;
ScreenManager manager;

manager.setScene(&gamescene);

4 个答案:

答案 0 :(得分:1)

你需要一个具体的派生类:

class MyScene: public Scene {

public:
   MyScene(void){}
   virtual ~MyScene(void){}
   virtual void update();
   virtual void render();
};

void setScene(Scene * sc)将是:

void setScene(Scene *sc)
{
  curSc = (Scene*)sc;
}
在这种情况下,

sc将是MyScene指针。无法创建抽象类实例(即接口),而Scene只是一个接口。

答案 1 :(得分:0)

完全。你做不到

curSc = new Scene  

因为它是抽象的。如果您确实要声明Scene的实例,那么请将其设为非抽象。即实施所有方法。

OR (我认为这是您打算做的)创建一个继承自Scene并实现所有虚拟方法的类。

class View : public Scene {

public:
   View(){}
   virtual ~View(void){}
   virtual void update();
   virtual void render();
};

并实现像

这样的虚拟方法
void View::update() {
//
}

void View::render() {
//
}

然后您可以将setScene实现为

void SceneManager::setScene(Scene *sc)
{
  curSc = sc;
}

并将其称为

SceneManager smag;
Scene *nsc = new View;
smag.setScene(nsc);

答案 2 :(得分:0)

在这里使用指针并没有错。但与引用不同,指针会促使其用户考虑NULL。这是警告。引用也可以引用NULL,但添加防御功能会引导您进入"dark side"。因此,假设引用将引用活动对象是合理的,在这种意义上,引用优于指针。

现在,如果你真的想要保留引用,你可以使用就地构造技术,因为你可以(重新)通过构造函数分配引用:

class SceneManager {

public:
    SceneManager(Scene& sc) : curSc(sc) {}
    ~SceneManager(void);
    SceneManager& setScene(Scene &sc) {
        SceneManager* cheatCompiler = new(this) SceneManager(sc);
        return *cheatCompiler;
    }
    Scene& curSc; 
}

请注意,这是一种古怪的东西。由于编译器总是试图超越我们,我无法保证它在所有情况下都能正常工作。

那说我还是建议你使用指针。如果您不想一直检查NULL,可以实现Null Object Pattern

之类的功能

答案 3 :(得分:0)

您应该使用智能指针,并且不要将成员变量公开。例如:

class Scene {
public:
    virtual ~Scene(){}
    virtual void update() = 0;
    virtual void render() = 0;
};

class MyScene : public Scene {
public:
    virtual void update () { /*...*/ }
    virtual void render () { /*...*/ }
};

class SceneManager {

public:
    SceneManager();
    ~SceneManager();
    void setScene(const std::shared_ptr<Scene> & sc) {
       curSc = sc;
    }
private:
    std::shared_ptr<Scene> curSc;
};

void someProc () {
    std::shared_ptr<Scene> sc = std::make_shared<MyScene> ();  
    auto manager = std::make_shared<SceneManager> ();
    manager->setScene (sc);
    // ...
}

如果没有智能指针,这看起来就像(但如果不再需要,请记住使用delete创建的对象new):

class Scene {
public:
    virtual ~Scene(){}
    virtual void update() = 0;
    virtual void render() = 0;
};

class MyScene : public Scene {
public:
    virtual void update () { /*...*/ }
    virtual void render () { /*...*/ }
};

class SceneManager {

public:
    SceneManager();
    ~SceneManager();
    void setScene(Scene * sc) {
       curSc = sc;
    }
private:
    Scene * curSc;
};

void someProc () {
    Scene * sc = new MyScene;
    SceneManager * manager = new SceneManager;
    manager->setScene (sc);
    // ...
}