返回一个多态类

时间:2017-05-13 17:30:10

标签: c++ class polymorphism

我正在创建一个小的xbox应用程序,并且一开始它应该检测当前正在运行的游戏,然后绕过和/或启动程序。由于我最近学习了多态性,我认为我可以在这里实现它以提高效率。下面是我的代码(效率不如我想的那样):

DWORD(__cdecl *XamGetCurrentTitleID)() = (DWORD(__cdecl *)())ResolveFunction("xam.xex", 0x1CF); // Resolves current Game ID

typedef enum _XBOX_GAMES : DWORD // Enum that holds Game IDs
{
    BOOT_UP = 0x00000000,
    DASHBOARD = 0xFFFE07D1,
    FREESTYLEDASH = 0xF5D20000,
    COD_WORLD_AT_WAR = 0x4156081C,
    COD_MODERN_WARFARE = 0x415607E6,
    COD_MODERN_WARFARE_2 = 0x41560817,
    COD_BLACK_OPS_1 = 0x41560855,
    COD_MODERN_WARFARE_3 = 0x415608CB,
    COD_BLACK_OPS_2 = 0x415608C3,
    COD_GHOSTS = 0x415608fC,
    COD_ADVANCED_WARFARE = 0x41560914,
    COD_BLACK_OPS_3 = 0x4156091D,
    DESTINY = 0x415608F8,
    GTAV = 0x545408A7
} XBOX_GAMES;

DWORD GameChecker()
{
    DWORD lastID = NULL;

    Game *game;
    AW aw; BO1 bo1; BO2 bo2; BO3 bo3; Ghosts ghosts; MW2 mw2; MW3 mw3; Dashboard dashboard;

    for (;;)
    {
        if (XamGetCurrentTitleID() != lastID)
        {
            switch (XamGetCurrentTitleID())
            {
                case BOOT_UP:
                    // nothing
                    break;
                case DASHBOARD:
                    game = &dashboard;
                    game->Launch();
                    break;
                case COD_MODERN_WARFARE_2:
                    game = &mw2;
                    game->Launch();
                    break;
                case COD_MODERN_WARFARE_3:
                    game = &mw3;
                    game->Launch();
                    break;
                case COD_GHOSTS:
                    game = &ghosts;
                    game->Bypass();
                    game->Launch();
                    break;
                case COD_BLACK_OPS_1:
                    game = &bo1;
                    game->Launch();
                    break;
                case COD_BLACK_OPS_2:
                    game = &bo2;
                    game->Bypass();
                    break;
                case COD_BLACK_OPS_3:
                    game = &bo3;
                    game->Bypass();
                    break;
                case COD_ADVANCED_WARFARE:
                    game = &aw;
                    game->Bypass();
                    game->Launch();
                    break;
            }

            lastID = XamGetCurrentTitleID();
        }
    }

    return 0;
}

正如你所看到的那样,我可以移动游戏 - >在switch语句之外启动()和game-> Bypass()以获得更少的代码并且只调用一次,但我没有&#39 ;我知道如何确定游戏何时需要绕行和/或启动。这是我的GameClass:

class Game
{
public:
    virtual void Bypass() { }

    virtual void Launch() { }
};

这是一个示例游戏的类:

// needs bypass and launch called
class AW : public Game
{
public:
    void Bypass()
    {
        // bypass
    }

    void Launch()
    {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

我想知道是否有办法做这样的事情:

DWORD GameChecker()
{
    DWORD lastID = NULL;

    Game *game;

    for (;;)
    {
        if (XamGetCurrentTitleID() != lastID)
        {
            switch (XamGetCurrentTitleID())
            {
                case BOOT_UP:
                    // nothing
                    break;
                default:
                    game = &functionThatReturnsClassBasedOnGame(XamGetCurrentTitleID()); // I don't know how to code such an function
                    break;
            }

            if (game->needsBypass)
                game->Bypass();

            if (game->needsLaunch)
                game->Launch();

            lastID = XamGetCurrentTitleID();
        }
    }

    return 0;
}

非常感谢任何帮助!谢谢你的时间。

1 个答案:

答案 0 :(得分:1)

完成示例的一种简单方法是:

const int NEEDS_BYPASS = 1;
const int NEEDS_LAUNCH = 2;

class Game
{
public:
    virtual ~Game() { }
    virtual int getFeatures() const { return 0; }
    virtual void Bypass() { }
    virtual void Launch() { }
};

class Game_Dashboard : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Dashboard - Loaded!");
    }
};

class Game_ModernWarfare2 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW2 - Loaded!");
    }
};

class Game_ModernWarfare3 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW3 - Loaded!");
    }
};

class Game_Ghosts : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
    void Bypass() {
        // bypass...
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Ghosts - Loaded!");
    }
};

class Game_BlackOpts1 : public Game
{
public:
    int getFeatures() const { return NEEDS_LAUNCH; }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"BO1 - Loaded!");
    }
};

class Game_BlackOpts2 : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS; }
    void Bypass() {
        // bypass...
    }
};

class Game_BlackOpts3 : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS; }
    void Bypass() {
        // bypass...
    }
};

class Game_AdvancedWarfare : public Game
{
public:
    int getFeatures() const { return NEEDS_BYPASS | NEEDS_LAUNCH; }
    void Bypass() {
        // bypass
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

Game* getGame(DWORD ID)
{
    switch (ID)
    {
    case DASHBOARD:
        return new Game_Dashboard;
    case COD_MODERN_WARFARE_2:
        return new Game_ModernWarfare2;
    case COD_MODERN_WARFARE_3:
        return new Game_ModernWarfare3;
    case COD_GHOSTS:
        return new Game_Ghosts;
    case COD_BLACK_OPS_1:
        return new Game_BlackOpts1;
    case COD_BLACK_OPS_2:
        return new Game_BlackOpts2;
    case COD_BLACK_OPS_3:
        return new Game_BlackOpts3;
    case COD_ADVANCED_WARFARE:
        return new Game_AdvancedWarfare;
    }
    return NULL;
}

DWORD GameChecker()
{
    DWORD currentID, lastID = 0;
    Game *game;

    do
    {
        currentID = XamGetCurrentTitleID();
        if (currentID != lastID)
        {
            lastID = currentID;

            game = getGame(currentID);
            if  (game)
            {
                if (game->getFeatures() & NEEDS_BYPASS)
                    game->Bypass();

                if (game->getFeatures() & NEEDS_LAUNCH)
                    game->Launch();

                delete game;
            }
        }
    }
    while (true);

    return 0;
}

然而,更好地使用多态将更像是这样:

class Game
{
public:
    virtual ~Game() { }
};

class CanBypass
{
public:
    virtual void Bypass() = 0;
};

class CanLaunch
{
public:
    virtual void Launch() = 0;
};

class Game_Dashboard : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Dashboard - Loaded!");
    }
};

class Game_ModernWarfare2 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW2 - Loaded!");
    }
};

class Game_ModernWarfare3 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"MW3 - Loaded!");
    }
};

class Game_Ghosts : public Game, public CanBypass, public CanLaunch
{
public:
    void Bypass() {
        // bypass...
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"Ghosts - Loaded!");
    }
};

class Game_BlackOpts1 : public Game, public CanLaunch
{
public:
    void Launch() {
        Sleep(500);
        XNotifyUI(L"BO1 - Loaded!");
    }
};

class Game_BlackOpts2 : public Game, public CanBypass
{
public:
    void Bypass() {
        // bypass...
    }
};

class Game_BlackOpts3 : public Game, public CanBypass
{
public:
    void Bypass() {
        // bypass...
    }
};

class Game_AdvancedWarfare : public Game, public CanBypass, public CanLaunch
{
public:
    void Bypass() {
        // bypass
    }
    void Launch() {
        Sleep(500);
        XNotifyUI(L"AW - Loaded!");
    }
};

Game* getGame(DWORD ID)
{
    switch (ID)
    {
    case DASHBOARD:
        return new Game_Dashboard;
    case COD_MODERN_WARFARE_2:
        return new Game_ModernWarfare2;
    case COD_MODERN_WARFARE_3:
        return new Game_ModernWarfare3;
    case COD_GHOSTS:
        return new Game_Ghosts;
    case COD_BLACK_OPS_1:
        return new Game_BlackOpts1;
    case COD_BLACK_OPS_2:
        return new Game_BlackOpts2;
    case COD_BLACK_OPS_3:
        return new Game_BlackOpts3;
    case COD_ADVANCED_WARFARE:
        return new Game_AdvancedWarfare;
    }
    return NULL;
}

DWORD GameChecker()
{
    DWORD currentID, lastID = 0;
    Game *game;
    CanBypass *bypasser; 
    CanLaunch *launcher;

    do
    {
        currentID = XamGetCurrentTitleID();
        if (currentID != lastID)
        {
            lastID = currentID;

            game = getGame(currentID);
            if  (game)
            {
                bypasser = dynamic_cast<CanBypass*>(game);
                if (bypasser)
                    bypasser->Bypass();

                launcher = dynamic_cast<CanLaunch*>(game);
                if (launcher)
                    launcher->Launch();

                delete game;
            }
        }
    }
    while (true);

    return 0;
}