C ++:使用虚函数解耦接口/实现?

时间:2009-12-23 15:57:48

标签: c++ interface

在过去的几个月里,我被Java宠坏了!我有一个C ++项目,我想将类接口(.h文件)与其实现细节分离。但是类的成员字段必须在它的声明中,如果我想调整类的成员字段,似乎我有这个不可避免的依赖关系。

我知道一种方法是使用多态+类继承(使接口成为基类,使实现成为派生类),但如果我没记错,那就需要虚函数,这是我想要的避免 - 这是在DSP上,有利的是不要过于“C ++ - y”。

有什么建议吗?

4 个答案:

答案 0 :(得分:12)

您需要PIMPL idiom

答案 1 :(得分:2)

你知道,我考虑过这个以及你对PIMPL的反对意见。

我有一个丑陋的黑客,我有时用于这样的情况,我怨恨付出间接罚款。虽然通常我的抱怨是调用new,而不是使用指针取消引用。我这样展示了我的丑陋黑客:

//  IHaveOpaqueData.h

class IHaveOpaqueData {
 public:
    // To make sure there are no alignment problems, maybe ::std::uin64_t
    typedef maximally_aligned_type_t internal_data_t[32];  // Some size I hope is big enough

    void iCanHazMemberFunction();
    // ...
 private:
    internal_data_t data;
};

//  IHaveOpaqueData.cpp
#include <boost/static_assert.hpp>

namespace { // Hide it in an anonymous namespace
struct RealData {
    int icanhazmembervariable_;
    double icanhazdoublevariable_;
};
BOOST_STATIC_ASSERT(sizeof(RealData) < sizeof(IHaveOpaqueData::internal_data_t);
}

void IHaveOpaqueData::iCanHazMemberFunction()
{
    // Use a reference to help the optimize make the right decision
    RealData &datathis = *(reinterpret_cast<RealData *>(&(this->data)));
    datathis.icanhazmembervariable_ = datathis.icanhazdoublevariable_;
}

是的,这很难看。 BOOST_STATIC_ASSERT(或者如果你有一个C ++ [01] x编译器,static_assert关键字)有助于使它不是一个完全的灾难。可能有一种聪明的方法可以使用工会来减轻我对齐问题的一些麻烦。

答案 2 :(得分:1)

使用pimpl习语。请在此处阅读:http://www.devx.com/cplus/Article/28105/0/page/3

它将有助于将实现与接口分离,并将减少(至少)所有编译依赖性。您甚至可以避免虚拟功能。

答案 3 :(得分:0)

这是一个古老的想法:) - 不透明的数据类型加上一组函数,即“在那里再返回[再到C]”:


// oi.hpp
namespace oi // old idea
{
    struct opaque; // forward declaration

    void init( opaque& ); // ctor
    void fini( opaque& ); // dtor

    int get_foo( const opaque& ); // getter
    void set_foo( opaque&, int ); // setter
}
// oi.cpp
namespace oi
{
    struct opaque // definition
    {
        int foo_; // data members
        // ...
    };

    // function definitions
}

通过引用访问结构的运行时成本可能与pimpl相同,所以这可能是一个较差的解决方案,因为一些重要的习惯用法如RAII无法使用。