【问题标题】:C++ : Cannot declare field to be of abstract typeC++:不能将字段声明为抽象类型
【发布时间】:2010-11-28 10:05:13
【问题描述】:

我在编译时收到此错误 -> 无法将字段 M1::sc 声明为抽象类型 I1,因为以下虚函数在 I1 中是纯的。请帮忙。

   class I1
    {    
    public:  
        virtual void a(int dir) = 0;
        virtual void b() = 0; 
        virtual void c() = 0; 

        void a(int dir) {  
        ....
        }

        void b() {  
        ....
        }

        void c() {  
        ....
        }
    };

    class I2 : public I1
    {    
    public:  


        void a(int dir) {  
        ....
        }

        void b() {  
        ....
        }

        void c() {  
        ....
        }
    }; 

    class M1 : public G1
    {
    protected:
    I1 sc;
    public:
       int dir = 4;
       sc.a(dir);
    };

完整的代码可以在http://pastebin.com/PFrMTJuF找到。

【问题讨论】:

  • 您真正想要的可能是sc 成为I1 const&

标签: c++ abstract-class


【解决方案1】:

Abstract classes 无法实例化,但您要求编译器通过将 I1 的实例嵌入到 M1 的每个实例中来做到这一点。

您可以通过稍微改变您的设计并将 指针(或智能指针,如果可以使用的话)嵌入到 I1 的实例来解决这个问题:

class M1 : public G1
{
protected:
    I1 *sc;
public:
    M1(I1 *sc_) {
        sc = sc_;
    }
    void foo() {
        int dir = 4;
        sc->a(dir);
    }
};

编辑:阅读您的代码后,我认为解决您的问题的最简单和最干净的方法是将当前房间传递给您的命令的 Execute() 方法,例如类似:

class ICommand
{
public:
    virtual ~ICommand()
    {
    }

    virtual void Execute(Room *room) = 0;
};


class MoveCommand : public GameCommand
{
public:
    MoveCommand()
    {
    }

    void Execute(Room *room)
    {
        // Do something with `room`...
    }
};


void Game::HandleInput()
{
    // Read command from user and generate a command object from it.
    ICommand *pCommand = ParseCommand(Input::ReadCommand());
    if (pCommand) {
        pCommand->Execute(GetCurrentRoom());  // Pass current room to command.
        delete pCommand;
    }
}

【讨论】:

  • sc_ 代表什么?我可以这样使用它吗?
  • @user, sc_ 是构造函数参数,需要创建M1 的实例。在我的示例中,它应该指向派生自I1 的具体类的实例,并提供a()b()c() 的实现。例如。 I2 的一个实例可以工作。
  • 请问我可以把我的代码发给你吗?我是 C++ 新手,我无法真正描述所有内容,因为我的项目中有几个文件链接在一起。
  • @user,您可以将该代码添加到您的问题中(或者如果它太大,则添加到该代码的链接),以便@Konrad 和其他人也可以看到它:)
  • 我认为拥有抽象类是个好主意,因为我为不同的房间有不同的派生类
【解决方案2】:

I1 是一个抽象类,因为它具有纯虚函数(= 没有定义的函数)。

您不能创建抽象类的实例(因为它们将如何工作?!),因此像 I1 a 这样的声明不起作用。

在您对问题进行编辑后,似乎 I1 不应该是一个抽象类,因为您为这些方法提供了定义。如果是这种情况,只需删除方法声明后的 = 0 即可使代码正常工作。

【讨论】:

  • 我能做什么?请指教。
  • 一种常见的解决方法是使用(智能)指针。当您初始化该指针时,您将创建一个非抽象派生类的实例。指针隐式转换为更一般(但抽象)的情况。这是有效的,因为实际实例提供了方法实现——即使指针类型不知道应用哪些实现,也可以在运行时确定。
  • 请问我可以把我的代码发给你吗?我是 C++ 新手,我无法真正描述所有内容,因为我的项目中有几个文件链接在一起。
  • 如果使用成员初始化列表怎么样?那么I1 a 不是实例化,而是使用派生对象创建的。
【解决方案3】:

您不能为抽象类(具有一个或多个纯虚函数的类)创建实例。 还有另一个问题。当您在类声明中调用函数sc.a(dir) 时,您希望编译器做什么? dir = 4这行也是错误的,类声明中只能初始化类的静态const成员。

【讨论】:

  • 其实就是 int dir = NORTH;其中 NORTH 在其中一个包含的文件中定义为枚举 RoomId { EAST, WEST, SOUTH, NORTH} 中的全局变量
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-07-23
  • 2015-09-11
  • 1970-01-01
  • 2013-11-15
  • 1970-01-01
  • 2021-12-07
  • 2021-06-10
相关资源
最近更新 更多