【问题标题】:"Member access into incomplete type" error, C++ Xcode SDL [closed]“成员访问不完整类型”错误,C++ Xcode SDL [关闭]
【发布时间】:2019-12-26 19:35:59
【问题描述】:

我收到错误“成员访问不完整类型”,我不知道为什么。我试图让玩家跳跃并降落在地面上,然后在地面上行走,但截至目前,我无法让玩家使用以下代码向下移动

                    case SDLK_SPACE:
                        transform->velocity.y = 3;
                        sprite->Play("Walk Side");
                    break;

但是当它检测到碰撞时我想要的是velocity.y = 0,这样他就可以走到那个地方。

组件.h

#ifndef Components_h
#define Components_h
#include "ECS.hpp"
#include "TransformComponent.h"
#include "SpriteComponent.h"
#include "ColliderComponent.h"
#include "KeyboardController.h"
#include "TileComponent.h"


#endif /* Components_h */

对撞机组件.h

#ifndef ColliderComponent_h
#define ColliderComponent_h

#include <string>
#include "SDL2/SDL.h"
#include "Components.h"
#include "TextureManager.hpp"

class ColliderComponent : public Component
{
public:
    SDL_Rect collider;
    std::string tag;

    SDL_Texture* tex;
    SDL_Rect srcR, destR;

    TransformComponent* transform;

    ColliderComponent(std::string t)
    {
        tag = t;
    }

    ColliderComponent(std::string t, int xpos, int ypos, int size)
    {
        tag = t;
        collider.x = xpos;
        collider.y = ypos;
        collider.h = collider.w = size;
    }

    void init() override
    {
        if(!entity->hasComponent<TransformComponent>())
        {
            entity->addComponent<TransformComponent>();
        }
        transform = &entity->getComponent<TransformComponent>();

        tex = TextureManager::LoadTexture("/Users/Shared/Relocated Items/Security/2D game engine/2D game engine - Textures/assets/PlatformWorldTest_ColliderTileSet.png");
        srcR = { 0, 0, 32, 32 };
        destR = { collider.x, collider.y, collider.w, collider.h };
    }

    void update() override
    {
        if(tag != "terrain")
        {
            collider.x = static_cast<int>(transform->position.x);
            collider.y = static_cast<int>(transform->position.y);
            collider.w = transform->width * transform->scale;
            collider.h = transform->height * transform->scale;
        }

        destR.x = collider.x - Game::camera.x;
        destR.y = collider.y - Game::camera.y;
    }

    void draw() override
    {
        TextureManager::Draw(tex, srcR, destR, SDL_FLIP_NONE);
    }

};

#endif /* ColliderComponent_h */

KeyboardComponent.h

#ifndef KeyboardController_h
#define KeyboardController_h

#include "Game.hpp"
#include "ECS.hpp"
#include "Components.h"

class KeyboardController : public Component
{
public:
    TransformComponent *transform;
    SpriteComponent *sprite;
    ColliderComponent *collision;

    void init() override
    {
        transform = &entity->getComponent<TransformComponent>();
        sprite = &entity->getComponent<SpriteComponent>();
        collision = &entity->getComponent<ColliderComponent>();
    }

    void update() override
    {
        if(Game::event.type == SDL_KEYDOWN)
        {
            switch (Game::event.key.keysym.sym)
            {
                /*case SDLK_w:
                    transform->velocity.y = -1;
                    sprite->Play("Walk Back");
                    break;*/
                case SDLK_a:
                    transform->velocity.x = -1;
                    sprite->Play("Walk Side");
                    sprite->spriteflip = SDL_FLIP_HORIZONTAL;
                    break;
                case SDLK_d:
                    transform->velocity.x = 1;
                    sprite->Play("Walk Side");
                    break;
                /*case SDLK_s:
                    transform->velocity.y = 1;
                    sprite->Play("Walk Forward");
                    break;*/
                case SDLK_SPACE:
                    transform->velocity.y = -3;
                    sprite->Play("Walk Side");
                    break;
                default:
                    break;
            }
        }

        if(Game::event.type == SDL_KEYUP)
        {
            switch (Game::event.key.keysym.sym)
            {
                /*case SDLK_w:
                    transform->velocity.y = 0;
                    sprite->Play("Idle");
                    break;*/
                case SDLK_a:
                    transform->velocity.x = 0;
                    sprite->Play("Idle");
                    sprite->spriteflip = SDL_FLIP_NONE;
                    break;
                case SDLK_d:
                    transform->velocity.x = 0;
                    sprite->Play("Idle");
                    break;
                /*case SDLK_s:
                    transform->velocity.y = 0;
                    sprite->Play("Idle");
                    break;*/
                case SDLK_SPACE:
                   #ifndef ColliderComponent_h
                   #error Not seen
                   #endif
                    if(collision->tag != "terrain") //ERROR IS HERE WITH POINTER ->, "Member access into incomplete type 'ColliderComponent'"
                    {
                        transform->velocity.y = 3;
                        sprite->Play("Walk Side");
                    }
                    else
                    {
                    transform->velocity.y = 0;
                    sprite->Play("Walk Side");
                    }
                    break;
                case SDLK_ESCAPE:
                    Game::isRunning = false;
                default:
                    break;
            }
        }

    }
};
#endif /* KeyboardController_h */

【问题讨论】:

  • 您如何期望ColliderComponent 的定义在出现错误的地方变得可见?无论您的答案是什么,请通过在错误行之前插入#ifndef ColliderComponent_h \n #error Not seen. \n #endif 来证明。
  • 我不确定我是否关注?
  • 您的问题是通过指向未知类的指针进行访问。必须查看该类的定义/声明。它在另一个标题中。我没有看到它被包含在哪里。请解释包含应该如何使其可见。如果你不能,那么这就是你的问题的原因。
  • 感谢您将我提议的行编辑成显示的代码。然而,这并没有帮助。您需要尝试编译并报告结果。我希望收到一条错误消息。
  • 好吧,猜到了。制作minimal reproducible example。请在“最小”上花费额外的精力。 IE。丢弃不需要重现所描述的错误消息的任何内容。

标签: c++ sdl member


【解决方案1】:

不要将函数KeyboardController::init()KeyboardController:: update() 直接定义到.h 中,而是在类的.cpp 中定义,然后在这个cpp 文件中添加#include "ColliderComponent.h",您的问题就会消失。

通常在一个好的项目中,您需要在 .h 文件中包含零个 #include,只需要前向声明,这对于编译时间会更好。

【讨论】:

  • 这并没有追踪问题的机制,而是提供了一个paushal的解决方案。然而,这是合适的(在没有模板等的情况下)。体面。
【解决方案2】:

问题在于您的包含。由于ColliderComponent.h 包含Components.h,它将开始递归地包含Components.h 中的所有文件。因此,当包含Components.h 时,它会尝试再次包含ColliderComponent.h,但由于包含保护,它将忽略其内容,并继续包含KeyboardComponent.h。此时,ColliderComponent没有完全定义。事实上,它实际上并没有从您显示的代码中定义,所以我假设某处有它的前向声明。您的 #ifndef … #error 不会引发编译错误,因为此时 ColliderComponent.h 已经(部分)包含在内,因此 ColliderComponent_h 已经定义。

最好的解决方案可能只是将函数定义移动到一个单独的源文件中,其中包括CompilerComponent.h 标头。此外,尝试从标题中删除不需要的 #includes,并坚持使用前向声明。

【讨论】:

  • 这就是我的想法。没有来自 OP 的反馈,只是有点过多的猜测。还是不错的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多