在尝试实现PIMPL idom

时间:2017-03-24 19:39:29

标签: c++ pimpl-idiom

我正在尝试使用PIMPL惯用法 - 从用户隐藏类的实现细节。我还希望通过隐藏实现类的实际名称来更进一步。这也应该允许我通过改变一行代码来快速交换实现类。

我的方法如下:

在头文件中,我定义了一个Public类,并声明了实现类的代理名称Implementation

X.h:

#pragma once

namespace detail {
class Implementation;
}

class Public {
public:
  Public();
  void foo();
private:
  detail::Implementation* data;
};

在实现中,我定义了实际的实现类(使用不同的名称),然后使用typedef将Implementation设置为我选择的类。

X.cpp

#include <iostream>
#include "X.h"

namespace {
class Private { //the actual implementation class. Everything about it, including its name, should be hidden
public:
  void foo() { std::cout << "Hello world!" << std::endl; }
};
}

namespace detail {
typedef Private Implementation; //set Private as the actual Implementation
}

Public::Public() : data(new detail::Implementation()) {}

void Public::foo() {
  data->foo();
}

不幸的是我收到了错误:

error C2371: 'detail::Implementation': redefinition; different basic types

typedef行。但是在两个位置(cpp和h文件)我声明了一个类;一个提供定义,另一个没有。那我错过了什么?

如果由于某些原因无法使用typedef(或C ++ 11 using),我还能如何实现目标呢?

我见过有关同一错误的类似问题,但我发现的只是一些微不足道的错误,例如:

2 个答案:

答案 0 :(得分:1)

将您的typedef放入头文件中,并删除Implementation的声明。

您宣布Implementation两次。在class Implementation;后再次在typedef Private Implementation;

如果您想要隐藏Private类型make Public模板化:

template<typename Implementation>
class Public
{
     ......
     Implementation * data;
     ......
};

然后在您的cpp中,您可以将您的私有实现声明为:

Public<Private> my_thing;

您可以使用最初计划的typedef隐藏模板:

typedef Public<Private> ExposedClass

答案 1 :(得分:0)

  

定义实际的实现类(使用不同的名称),然后使用typedef将Implementation设置为我选择的类。

这就是问题所在。你不能。 typedef名称不是类。通过说class Implementation,您承诺Implementation将被定义为实际的类,而不是typedef名称。

摆脱typedef并将Private重命名为Implementation