KKMKK
KKMKK

Reputation: 97

Instance of class which inherit from abstract class

I have to create the instance of class which inherits from abstract class. My code is really simple. It should create the instance of object class based on abstract class. The abstract class is template class aswell. Then I need to put this object into storage class which holds pointer to the object. Thats all. This task is some kind of homework.

Is that even possible to create the instance of class based on abstract class?

If yes - what I am doing wrong? If no - how can I make it similar?

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

Compiling Errors:

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;

Upvotes: 0

Views: 2175

Answers (2)

Maroš Beťko
Maroš Beťko

Reputation: 2339

Ok so I'll go over the errors in your code in an order they would execute from the start of main function.

  1. To initialize shared_ptr you should use a dedicated function make_shared. It's always better to not use new if possible and leave the memory handling to classes written for that purpose (such as shared_ptr you are using).
  2. From your question I assume that you wanted to create a child object and save it as ITERFACE. Saving derived classes as their base class reference/pointer is valid.
  3. It would be better to use unique_ptr instead of shared_ptr inside storage class. The name of the class says, that it stores the data, therefore owns it.
  4. Since storage should have it's data saved as unique_ptr, newChild should also be a unique_ptr and then just swap the ownership with the storage
  5. You can't just assign any smart pointer such as shared_ptr. They are responsible for memory they hold and you need to call dedicated functions such as get or swap to manipulate the data they hold.
  6. In the INTERFACE you have your 2 virtual set methods of type type2 setX(). One would expect for them to take as an argument the value they should set given attribute to. The = 0 you used there, means that the method is not implemented and that the inheriting classes should implement it. This right because as the name INTERFACE says, it's only an interface, showing publicly what can be done with class inheriting it, and not actually having any functionality.
  7. Set functions in your child class are missing the override keyword, which tells the compiler that these methods should override functions in base class. Since you have the base classe's implementations wrong, it didn't tell you anything.

I hope i went over all of the issues. If I find anything else or someone else mentions anything I'll add it to the list. And here is an example with all the issues fixed:

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

I've also refactored your code a bit to follow conventions I like to use in my code. Hope I have gone over all the issues and if you have any other questions, feel free to ask.

P.S.: I don't have an access to a C++ compiler right now so hopefully my provided code will compile without problems.

Upvotes: 1

AdvSphere
AdvSphere

Reputation: 986

You have two main issues:

  1. The arguments in interfaces are missing.
  2. In your derived class you must return values for "setX() and Y", however I wouldn't since the name implies it only "sets", is not a 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;
        }
    

Upvotes: 0

Related Questions