从抽象类继承的类实例

时间:2018-01-22 22:52:39

标签: c++ templates inheritance abstract-class

我必须创建继承自抽象类的类实例。 我的代码非常简单。它应该基于抽象类创建对象类的实例。抽象类也是模板类。然后我需要将此对象放入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;

2 个答案:

答案 0 :(得分:1)

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

  1. 要初始化shared_ptr,您应使用专用函数make_shared。如果可能的话,最好不要使用new并将内存处理留给为此目的而编写的类(例如您正在使用的shared_ptr)。
  2. 根据您的问题,我假设您要创建一个child对象并将其另存为ITERFACE。将派生类保存为其基类引用/指针是有效的。
  3. 最好在unique_ptr课程中使用shared_ptr代替storage。该类的名称表示它存储数据,因此拥有它。
  4. 由于storage应将其数据保存为unique_ptr,因此newChild也应为unique_ptr,然后只需将所有权与storage交换
  5. 您无法分配任何智能指针,例如shared_ptr。他们负责记忆,您需要调用getswap等专用函数来操纵他们持有的数据。
  6. INTERFACE中,您有2种类型为type2 setX()的虚拟集方法。人们可以期望他们将属性赋予他们应该设置的值作为参数。您在那里使用的= 0意味着该方法未实现,并且继承类应该实现它。这是正确的,因为名称INTERFACE表示,它只是一个界面,公开显示继承它的类可以做什么,而实际上没有任何功能。
  7. child类中的集合函数缺少override关键字,它告诉编译器这些方法应该覆盖基类中的函数。由于你的基础classe的实现错误,它没有告诉你任何事情。
  8. 我希望我能解决所有问题。如果我发现任何其他内容或其他人提到任何内容,我会将其添加到列表中。以下是修复所有问题的示例:

    #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 ++编译器,所以希望我提供的代码可以毫无问题地编译。

答案 1 :(得分:0)

您有两个主要问题:

  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;
        }