【问题标题】:error C2259: 'class' : cannot instantiate abstract class错误 C2259:“类”:无法实例化抽象类
【发布时间】:2014-07-19 02:04:18
【问题描述】:

现在,我对抽象类有了很多了解,但是,我最近尝试使用抽象类来创建一个虚函数来接收消息,然后是另一个具有std::vector 智能指针的类这个类,但后来我得到了错误 C2259。 (是的,我确实查过here

旁注:

我最近也阅读了大量有关智能指针的内容,因为在与指针相关的每个问题中几乎(如果不是总是)都提到了它们。所以我决定第一次尝试实现它们,所以我的问题实际上可能是因为我对智能指针的使用不当。

不管怎样,这里是纯抽象类本身——

//Component.h

namespace rpg
{

class Component
{
public:
    virtual void Receive(rpg::Message message) = 0;

    Component();
    virtual ~Component();
};

这是尝试使用纯抽象类时出错的类。

//ContainerObject.h

#include <vector>
#include <memory>
#include "Component.h"

namespace rpg
{

class ContainerObject
{
private:
    //Create short name for a vector of smart pointers to the pure abstract class
    typedef std::vector<std::shared_ptr<rpg::Component>> ComponentList;

    //Create array of Components (std::vector).
    ComponentList myComponents;

public:
    //Send message to all Components in array (std::vector)
    void Send(rpg::Message message)
    {
        if(myComponents.size() > 0)
        {
            for(int i = 0; i < myComponents.size(); i++)
            {
                if(myComponents[i] != NULL)
                {
                    myComponents[i]->Receive(message);
                }
            }
        }
    } // end of Send()

    //Add new Component to array (std::vector)
    void AddComponentToMessageList(rpg::Component& component)
    {
        myComponents.push_back(std::make_shared<rpg::Component>(component));
    }

    ContainerObject();
    ~ContainerObject();
};

} //namespace rpg

首先,我正在尝试练习更好的代码组织(我正在学习一些here here 的内容,我在页面底部附近看到他们仍然声明了一个指向纯抽象类对象的指针列表,所以我很确定我可以这样使用它,所以为什么我收到错误 C2295,我该如何解决?我可能在哪里实例化它,是什么导致它被实例化?

(我认为实例化一词可能是真正让我感到困惑的部分,这就是为什么我还问是什么原因造成的,所以如果你也可以在你的答案中包含它,那将不胜感激。(我确实谷歌了它的定义; 我还是一头雾水))

【问题讨论】:

    标签: c++ oop abstract-class smart-pointers


    【解决方案1】:
    void AddComponentToMessageList(std::shared_ptr<rpg::Component>& component)
    {
        myComponents.push_back(component);
    }
    

    尝试这种方式并在调用 AddComponentToMessageList 函数之前使用 std::make_shared 创建对象。我从未尝试使用复制构造函数来实例化带有智能指针的类。乍一看它应该可以工作,但你永远不知道。

    另一个注释。比抽象类更喜欢接口。意思是创建一个如下所示的 IComponent 接口:

    class IComponent
    {
    public:
        virtual void Receive(rpg::Message message) = 0;
        virtual ~Component() { };
    };
    

    然后让你的类实现这个接口。显然你的向量需要改变,成为 std::shared_ptr 的容器。

    现在我还注意到,无论是通过“new”、堆栈还是 std::make_shared,您都无法创建抽象类。

    【讨论】:

    • 奇怪...将参数更改为可以使其完美运行。你会碰巧知道为什么吗? (如果可以的话,你能详细说明一下吗?)另外,你的IComponent 班级和我的Component 班级有什么区别?我确实打算让所有以后的组件继承我的Component 类。
    • 不同的是 IComponent 是一个接口。在 C++ 中,与 C# 不同,没有 interface 关键字。所以我们最终创建了一个没有实现方法的抽象类。除了析构函数。我不确定为什么我们不能通过传递一个复制构造函数来使用 std::make_shared 创建一个类。智能指针可能不允许它,即使不要引用我的话,因为它没有任何意义。此外,如果您打算在整个代码中使用智能指针,则传递对象本身的引用然后将其包装在智能指针中是没有意义的。
    • 那是因为,你为什么要这么做?无论如何,您都将创建对象。如果是这种情况,则使用 std::make_shared 创建它。在您的情况下,您首先创建对象,然后创建其副本。这是您不需要的开销。
    • 就您项目中的其他实体而言。他们可以实现 IComponent 而不是 Component。这完全取决于您是否希望从 Component 派生的所有类都具有一些预定义的行为。如果是这种情况,那么抽象类就是要走的路。如果不是这种情况,那么您可以使用接口。
    • 我会在这个主题上做一些研究,因为我似乎缺乏接口方面的知识。另外...我必须删除void AddComponentToMessageList(std::shared_ptr&lt;rpg::Component&gt;&amp; component) 中的“&”才能真正正确地传递参数。否则它似乎工作正常,尺寸在增加,我将继续用它做实验。感谢您的帮助。
    【解决方案2】:

    当您在此行中调用 make_shared 时,您正在尝试实例化组件:

    myComponents.push_back(std::make_shared<rpg::Component>(component));
    

    make_shared 尝试执行 new rpg::Component(component) 失败,因为 Component 是抽象的。

    【讨论】:

    • 那你会推荐我做什么来代替这条线?
    • 按照 armanali 的建议做 - 更改您的函数以接收 shared_ptr,然后调用该函数的任何人都可以在具体类(以 Component 作为其基类)上创建共享指针。
    • 需要去掉函数参数定义中的&。不同类型的智能指针不能通过引用传递。嗯,你似乎已经删除了你的问题。希望您自己发现了这一点。
    • 我做到了。哈哈。谢谢你。当我发表评论后回去查看该功能时,当我看到它时,我基本上是在面对手掌。感谢您的确认,尽管这确实是问题所在。
    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-05-13
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    相关资源
    最近更新 更多