Best way to use a C++ Interface

余生长醉 提交于 2019-12-22 06:09:09

问题


I have an interface class similar to:

class IInterface
{
public:

    virtual ~IInterface() {}

    virtual methodA() = 0;

    virtual methodB() = 0;

};

I then implement the interface:

class AImplementation : public IInterface
{
    // etc... implementation here
}

When I use the interface in an application is it better to create an instance of the concrete class AImplementation. Eg.

int main()
{
    AImplementation* ai = new AIImplementation();
}

Or is it better to put a factory "create" member function in the Interface like the following:

class IInterface
{
public:

    virtual ~IInterface() {}

    static std::tr1::shared_ptr<IInterface> create(); // implementation in .cpp
    virtual methodA() = 0;

    virtual methodB() = 0;

};

Then I would be able to use the interface in main like so:

int main()
{
    std::tr1::shared_ptr<IInterface> test(IInterface::create());
}

The 1st option seems to be common practice (not to say its right). However, the 2nd option was sourced from "Effective C++".


回答1:


One of the most common reasons for using an interface is so that you can "program against an abstraction" rather then a concrete implementation.

The biggest benefit of this is that it allows changing of parts of your code while minimising the change on the remaining code.

Therefore although we don't know the full background of what you're building, I would go for the Interface / factory approach.

Having said this, in smaller applications or prototypes I often start with concrete classes until I get a feel for where/if an interface would be desirable. Interfaces can introduce a level of indirection that may just not be necessary for the scale of app you're building.

As a result in smaller apps, I find I don't actually need my own custom interfaces. Like so many things, you need to weigh up the costs and benefits specific to your situation.




回答2:


There is yet another alternative which you haven't mentioned:

int main(int argc, char* argv[])
{
   //...
   boost::shared_ptr<IInterface> test(new AImplementation);
   //...
   return 0;
}

In other words, one can use a smart pointer without using a static "create" function. I prefer this method, because a "create" function adds nothing but code bloat, while the benefits of smart pointers are obvious.




回答3:


There are two separate issues in your question: 1. How to manage the storage of the created object. 2. How to create the object.

Part 1 is simple - you should use a smart pointer like std::tr1::shared_ptr to prevent memory leaks that otherwise require fancy try/catch logic.

Part 2 is more complicated.

You can't just write create() in main() like you want to - you'd have to write IInterface::create(), because otherwise the compiler will be looking for a global function called create, which isn't what you want. It might seem like having the 'std::tr1::shared_ptr test' initialized with the value returned by create() might seem like it'd do what you want, but that's not how C++ compilers work.

As to whether using a factory method on the interface is a better way to do this than just using new AImplementation(), it's possible it'd be helpful in your situation, but beware of speculative complexity - if you're writing the interface so that it always creates an AImplementation and never a BImplementation or a CImplementation, it's hard to see what the extra complexity buys you.




回答4:


"Better" in what sense?

The factory method doesn't buy you much if you only plan to have, say, one concrete class. (But then again, if you only plan to have one concrete class, do you really need the interface class at all? Maybe yes, if you're using COM.) In any case, if you can forsee a small, fixed limit on the number of concrete classes, then the simpler implementation may be the "better" one, on the whole.

But if there may be many concrete classes, and if you don't want to have the base class be tightly coupled to them, then the factory pattern may be useful.

And yes, this can help reduce coupling -- if the base class provides some means for the derived classes to register themselves with the base class. This would allow the factory to know which derived classes exist, and how to create them, without needing compile-time information about them.




回答5:


Use the 1st method. Your factory method in the 2nd option would have to be implemented per-concrete class and this is not possible to do in the interface. I.e., IInterface::create() has no idea exactly which concrete class you actually wish to instantiate.

A static method cannot be virtual, and implementing a non-static create() method in your concrete classes has not really won you anything in this case.

Factory methods are certainly useful, but this is not the correct use.

Which item in Effective C++ recommends the 2nd option? I don't see it in mine (though I don't also have the second book). That may clear up a mis-understanding.




回答6:


I would go with the first option just because it's more common and more understandable. It's really up to you, but if your working on a commercial app then I would ask what my peers what they use.




回答7:


I do have a very simple question there:

Are you sure you want to use a pointer ?

This question might seem unlogical but people coming from a Java background use new much often than required. In your example, creating the variable on the stack would be amply sufficient.



来源:https://stackoverflow.com/questions/1198055/best-way-to-use-a-c-interface

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!