【问题标题】:Instance of class which inherit from abstract class从抽象类继承的类的实例
【发布时间】:2018-07-01 16:08:43
【问题描述】:

我必须创建从抽象类继承的类的实例。 我的代码真的很简单。它应该基于抽象类创建对象类的实例。抽象类也是模板类。然后我需要将此对象放入storage 类中,该类包含指向该对象的指针。就这样。这项任务是某种家庭作业。

甚至可以基于抽象类创建类的实例吗?

如果是 - 我做错了什么? 如果没有 - 我怎样才能让它相似?

#include <iostream>
#include <string>
#include <memory>

// using namespace std;

template<typename type1, typename type2, typename type3> class INTERFACE {
    protected:
        type1 x;
        type2 y;
        type3 name;

    public:
        virtual type1 setX() = 0;
        virtual type2 setY() = 0;
};

class child : public INTERFACE<int, float, std::string> {
    public:
        child(std::string z) {
            this->name = z;
        }

        int setX(int x) {
            this->x = x;
        } 

        float setY(float y) {
            this->y = y;
        }
};

class storage {
    private:
        std::shared_ptr<child> childPTR;

    public:
        void setPTR(const std::shared_ptr<child> & pointer) {
            this->childPTR = pointer;
        }
};

int main(){
  std::shared_ptr<child> newChild(new child("xxx"));
  storage testStorage;
  testStorage.setPTR(newChild);

    return 0;
}

编译错误:

templates.cpp: In function ‘int main()’:
templates.cpp:44:52: error: invalid new-expression of abstract class type ‘child’
     std::shared_ptr<child> newChild(new child("xxx"));
                                                    ^
templates.cpp:18:7: note:   because the following virtual functions are pure within ‘child’:
 class child : public INTERFACE<int, float, std::string> {
       ^
templates.cpp:14:23: note:  type1 INTERFACE<type1, type2, type3>::setX() [with type1 = int; type2 = float; type3 = std::__cxx11::basic_string<char>]
         virtual type1 setX() = 0;
                       ^
templates.cpp:15:23: note:  type2 INTERFACE<type1, type2, type3>::setY() [with type1 = int; type2 = float; type3 = std::__cxx11::basic_string<char>]
         virtual type2 setY() = 0;

【问题讨论】:

  • 使用override specifier。你会发现它很有启发性。特别是()(int x) 没有声明相同的参数列表。
  • 另外,标题是什么?
  • 很抱歉。误点击。应该是:Instance of class which inherits from abstract class
  • 你试图一次做太多新的事情。当您尝试实现新功能时,请单独处理它们,在它们完美运行之前不要将它们组合起来。
  • 然后edit您的帖子并将标题更正为应该是

标签: c++ templates inheritance abstract-class


【解决方案1】:

你有两个主要问题:

  1. 接口中的参数丢失。
  2. 在您的派生类中,您必须返回“setX() 和 Y”的值,但我不会,因为名称暗示它只是“sets”,而不是 getter。

    public:
        virtual auto setX(type1 x) ->decltype(x) = 0;
        virtual auto setY(type2 y) ->decltype(y) = 0;
    

    ...

        int setX(int x) {
            this->x = x;
            return x;
        }
    
        float setY(float y) {
            this->y = y;
            return y;
        }
    

【讨论】:

  • 顺便说一句,如果参数名称与成员名称相同,则只需要 this-&gt; 表示法。恕我直言,更改参数名称以删除 this-&gt; 表示法。
  • 是的,同意你的看法。只是把它留在那里以类似于他的代码。
【解决方案2】:

好的,我将按照它们从 main 函数开始执行的顺序检查代码中的错误。

  1. 要初始化shared_ptr,您应该使用专用函数make_shared。如果可能,最好不要使用new,并将内存处理留给为此目的编写的类(例如您正在使用的shared_ptr)。
  2. 根据您的问题,我假设您想创建一个child 对象并将其保存为ITERFACE。将派生类保存为其基类引用/指针是有效的。
  3. 最好在storage 类中使用unique_ptr 而不是shared_ptr。类的名称表明它存储数据,因此拥有它。
  4. 由于storage 应该将其数据保存为unique_ptr,newChild 也应该是unique_ptr,然后只需将所有权与storage 交换即可
  5. 您不能只分配任何智能指针,例如shared_ptr。他们负责他们持有的内存,您需要调用专用函数,例如 getswap 来操作他们持有的数据。
  6. INTERFACE 中有两个type2 setX() 类型的虚拟集合方法。人们会期望他们将他们应该设置给定属性的值作为参数。您在那里使用的= 0 表示该方法未实现,继承类应该实现它。这是正确的,因为正如名称 INTERFACE 所说,它只是一个接口,公开展示了类继承它可以做什么,实际上并没有任何功能。
  7. child 类中设置函数缺少override 关键字,它告诉编译器这些方法应该覆盖基类中的函数。由于您的基类实现错误,因此它没有告诉您任何信息。

我希望我能解决所有问题。如果我发现任何其他内容或其他人提及任何内容,我会将其添加到列表中。这是一个解决了所有问题的示例:

#include <iostream>
#include <string>
#include <memory>

template<typename Type1, typename Type2, typename Type3>
class Interface {
protected:
    Type1 x;
    Type2 y;
    Type3 name;

public:
    // setters with proper signature now
    virtual void setX(Type1) = 0;
    virtual void setY(Type2) = 0;
};

class Child: public Interface<int, float, std::string> {
public:
    Child(const std::string& z) { name = z; };

    void setX(int val) override { x = val; }
    void setY(float val) override { y = val; }
};

class Storage {
    // private keyword not needed
    // you also need to specify template arguments of the interface here
    std::unique_ptr<Interface<int, float, std::string>> _interface;
    // convention of prefixing private members with _

public:
    void setPointer(std::unique_ptr<Interface<int, float, std::string>>&& pointer) {
        // transfers ownership of that memory to _interface
        _interface = std::move(pointer);
    }
};

int main() {
    // make_unique creates an instance of child, passing it's arguments
    // to child's constructor and saves it inside an interface pointer
    std::unique_ptr<Interface<int, float, std::string>> newChild = std::make_unique<Child>("xxx");
    Storage testStorage;
    // here you must move the ownership to the setPointer function
    testStorage.setPointer(std::move(newChild));

    return 0;
}

我还对您的代码进行了一些重构,以遵循我喜欢在代码中使用的约定。希望我已经解决了所有问题,如果您有任何其他问题,请随时提出。

P.S.:我现在无法访问 C++ 编译器,所以希望我提供的代码能够顺利编译。

【讨论】:

  • 现在我遇到了很多错误。其中之一是:error: cannot convert ‘std::_MakeUniq&lt;child&gt;::__single_object {aka std::unique_ptr&lt;child&gt;}’ to ‘int’ in initialization std::unique_ptr&lt;INTERFACE&gt; p = std::make_unique&lt;child&gt;("xxx"); 我应该创建新帖子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 2010-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多