Corey Maddie Besmer
Corey Maddie Besmer

Reputation: 23

Instantiating c++ interface as a child class

I have an interface, let's call it Creature, who has virtual functions that cause it to be abstract.

I have child classes of this interface such as Dog, Cat, and Pig.

The compiler doesn't seem to like the following line due to not being able to declare variable thing to be of abstract type Creature.

Creature thing = Dog();

I know I can't instantiate interfaces and the like, but this is just a Dog being declared as a Creature.

I need some way of having one declaration work for all the children (i.e., being able to put Dog(), Cat(), or Pig() where Dog() is in the line above).

Can this be done in c++ or am I misusing inheritance and interfaces completely?

Upvotes: 2

Views: 6845

Answers (2)

Casper Beyer
Casper Beyer

Reputation: 2301

In C++ you have to realize the different between value and reference semantics, where-as in interpretet languages you tend to just deal with reference semantics (except for some odd cases with plain old data objects which have value semantics but besides the point).

In C++ all objects are values, e.g an object can never be null, this has the implication that declaration specifies the storage requirement. Consider the following

struct creature {
};

struct dog : public creature {
    float cuteness;
};

The storage requirement for a dog is different than that of a creature, even if you allow the conversion this would result in slicing. For example, will fido bark or be silent? #include

class creature {
public:
    virtual void speak() {
        std::cout << "..." << std::endl;
    }
};

class dog : public creature {
public:
    virtual void speak() {
        std::cout << "woof!" << std::endl;
    }
};

int main(int argc, const char *argv[]) {
    creature fido;
    fido = dog();

    fido.speak();
    return 0;
}

However if you were to simply have a pointer or reference to the object it is a different matter. By pointer.

creature* fido = new dog();
fido->speak();
delete fido;

By reference.

dog fido;
creature& c = fido;

c.speak();

Beyond the scope of this question, but optionally a smart pointer.

std::unique_ptr<creature> fido(new dog);

Upvotes: 1

Joseph Mansfield
Joseph Mansfield

Reputation: 110648

Object types themselves are not polymorphic in C++. The line you've given declares a Creature object and then attempts to initialise it with a Dog object. If Creature weren't abstract, this would result in slicing - thing wouldn't be a Dog any more, it would just be a Creature. Since it is abstract, you simply can't have a Creature object anyway.

You need to use pointers or references for polymorphic behaviour. Consider for example:

Creature* thing = new Dog();

You can now dereference thing and use it as a Creature, even though it's dynamic type is Dog. However, using raw pointers like this is usually not recommended, as you have to manually ensure that the object is deleted at some point. The ownership can become confusing. Your best bet is to put it in a smart pointer, such as:

std::unique_ptr<Creature> thing(new Dog()); // or std::make_unique when we have it

Here, I've demonstrated std::unique_ptr, but the choice of smart pointer will depend on the ownership semantics for that object. A common alternative is std::shared_ptr.

To demonstrate polymorphism with references:

Dog dog;
Creature& thing = dog;
// Can now use dog as a Creature

Upvotes: 9

Related Questions