我正在尝试使用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
),我还能如何实现目标呢?
我见过有关同一错误的类似问题,但我发现的只是一些微不足道的错误,例如:
答案 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
。