1

Please consider a pure virtual class like this:

class Foo {
    public: virtual int FooBar() = 0;
};

A Java developer would call such a thing an "Interface". Usually, you then program to that interface, e.g. (bad example, sorry):

class Bar {
    public: Foo f;
};

class Child : public Foo {
    public: int FooBar() { return 1; }
};

Bar b;
b.foo = Child();

This does obviously not work in C++, because an instance of class Foo is created at construction time (but that's not possible, because Foo is an abstract class).

Is there any pattern for "programming to an interface" in C++?

Edit: Clarified the example, sorry.

2
  • A java developer would not do that, he would use the "implements" keyword in order to implement the interface. Not declare it as a class member. Commented Aug 14, 2012 at 10:25
  • 1
    The code example is still terrible, and wouldn't work in Java either, since Bar is not a base class of Child. Commented Aug 14, 2012 at 11:08

6 Answers 6

3

If you need something, that points to or references an implementation of an interface (or abstract class), you can use a pointer of a reference to that interface:

class Bar {
public:
    Bar( Foo& af ) : f( af )
    {}
private: 
    Foo& f;
};

If you want to use a reference Foo& f, a pointer Foo* f or a reference or pointer to a const implementation (const Foo& f of const Foo* f) or even a const pointer to const implementation (const Foo* const f) depends on your requirements.

Use a reference if possible, for composition where the referenced implementation is passed from the outside (like in my example). Use a pointer or smart-pointer if the object is more of an aggregation and is constructed by the containing object itself.

Update: As no one else mentioned it up to now, if you are going to allocate the object that implements the interface dynamically, the base class have to have a virtual destructor, or otherwise you will invoke undefined behavior, even if you use a smart pointer. And beware that smart pointer can be handy, but they are not a cure for all. You should still keep some owner hierarchy in mind or you will end up with cycles that can't be resolved by smart pointers easily.

Sign up to request clarification or add additional context in comments.

3 Comments

Your examples reads like: The member "f" is a reference rather than an object, the constructor also gets passed a reference to an instance of "Foo" (or any subclass) and the bit f(af) stores this reference in the member variable "f" - is that correct?
@Niko - this is dangerous, be careful. In this case, you cannot do something like: b.f = Child();, because Child() will create a temporary object, then b.f will be a reference to this temp object and exactly after the ; in this row, the "child" will be destroyed! Then you'll have an invalid reference, thus, undefined behavoiur.
@KirilKirov Of cause, you have to know want you want to do, that's especial true for C++. As f is private, assigning will not work and if f would be public b.f = Child(); would slice the Child instance to a Foo and use the operator =( const Foo& )to assign the Temp to f. So, there is no danger.
3

Your data member f should be declared as a pointer to Foo or, even better, as some form of smart pointer to Foo, e.g. shared_ptr<Foo>.

You could use a reference to Foo, but that complicates things: your class would require an explicit constructor and not be copyable or assignable unless you implement both member functions explicitly.

1 Comment

Check out whether your standard library supports shared_ptr<>. If not you need the Boost libraries
3

In order to use polymorphism as in Java, you need to use pointers and references, just like in Java. In Java everything is either of a primitive type or a reference: when you write Foo f; in Java you get a reference. In C++ you get an object.

However, unlike in Java, an interface in C++ does not have to involve virtual functions and base classes. A good example of this are the iterator interfaces that are used in the standard library.

Comments

2

I think you need to inherit the "interface", not to use composition, don't you?

Like this

class Bar: public Foo
{
private: 
    virtual int Bar() { /* ... */ }
};

That's what I understand from "program to an interface".


EDIT: Ahaa, looking at your edit, you really need pointer here. Here's the equivalent C++ code:

class Foo {
    public: virtual int Bar() = 0;
};

class Bar {
    //.........v
    public: Foo* f;
};

class Child : public Foo {
    public: int Bar() { return 1; }
};

Bar b;
b.f = new Child();

But then you need to take care of the new allocated memory for Child(). To avoid this and make the code absolutely (logically) equivalent, you need smart pointers, for this case - a shared_ptr (C++11 , boost)

Comments

0

You are doing everything right with one exception. You need to derive from an interface, not include it as a member.

class myInterface
{
    virtual void foo() = 0;
}

class iHaveAnInterface: public myInterface
{
    void foo();
}

void iHaveAnInterface::foo()
{
    //implement
}

Comments

0

Interface in C++ are best written as abstract-base-classes: stateless classes containing at least one pure virtual function. Concrete classes derive publicly from the interface class and (optionally) add state to implement the interface.

class IFoo
{
public:
    // enable deletion of implementation classes through IFoo*
    virtual ~IFoo() {}

    // interface
    void bar() 
    { 
        // add optional pre-processing here
        do_bar(); 
        // add optional post-processing here
    }

private:
    // to be overridden by implementation classes
    virtual void do_bar() = 0; // pure virtual

    // no state here!
};

class FooImpl
:
    public IFoo
{
public:
    // constructors, assignment etc. to manipulate state

private:
    virtual void do_bar() 
    { 
         // your implementation 
    }

    // add your state here
};

void my_algorithm(IFoo* foo)
{
    foo->bar();
}

int main()
{
    IFoo* f = new FooImpl();
    my_algorithm(f); // resolves to using FooImpl::do_bar()

    return 0;
}

The above code is in terms of run-time polymorphism and explicit interfaces. There is an alternative in C++ using compile-time polymorphism and implicit interface. This is done using templates and the Curiously Recurring Template Pattern.

Note that I have used the Non-Virtual-Interface (NVI) idiom here: the public interface of IFoo is non-virtual, and the implementation is (pure) virtual. This gives writers of the interface more flexibility e.g. to add logging and other checking inside IFoo::bar() etc. without clients noticing.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.