我正在尝试使用 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/