c++ - 尝试实现 PIMPL 习语时如何避免 "redefinition; different basic types"

标签 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)因故无法使用,我还能如何实现我的目标?


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

最佳答案

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

您声明了两次 Implementation。一次在 class Implementation; 并再次在 typedef Private Implementation;

如果你想隐藏 Private 类型使 Public 模板化:

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

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

Public<Private> my_thing;

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

typedef Public<Private> ExposedClass

关于c++ - 尝试实现 PIMPL 习语时如何避免 "redefinition; different basic types",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43007848/

相关文章:

c++ - 哪种数据结构可以处理二维线段

c++ - 奇怪的 "type class::method() : stuff "语法 C++

c++ - 我如何从 uint8_t vector 创建一个 istream?

php - 如何在网页和实际程序之间进行交互

c++ - 多个 Pimpl 类互相使用

c++ - 是否可以使用右值引用作为 pimpl 句柄?

c++ - 与类成员变量一起使用的 Pimpl 习语

c++ - PIMPL,POD,实现类的可见性,它的析构函数会被调用吗?

c++ - 从 BCRYPT_SECRET_HANDLE 将共享 secret 导出为 BYTE 数组

c++ - 成员函数定义中的不完整类型