尝试实施 PIMPL idom 时如何避免"redefinition; different basic types"



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

我的方法如下:

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

X.h:

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

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

十.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++11using)由于原因无法使用,我还能如何实现我的目标?


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

  • 错误 C2371:重新定义;不同的基本类型 - 为什么? :在定义之前使用名称
  • 重定义;不同的基本
  • 类型(typedef 结构),或 重定义不同的基本类型 => typedef:忘记包含保护

把你的 typedef 放在你的头文件中,并删除Implementation的声明。

您声明Implementation两次。一次在class Implementation;,一次在typedef Private Implementation;

如果要隐藏Private类型,请Public模板化:

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

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

Public<Private> my_thing;

更好的是,您可以按照最初的计划使用 typedef 隐藏模板:

typedef Public<Private> ExposedClass

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

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

摆脱typedef并将Private重命名为Implementation

最新更新