不能使用 pimpl 习语将用户定义的向量插入到封装的向量中

Cannot insert user-defined into an encapsulated vector using pimpl idiom

本文关键字:向量 插入 封装 定义 用户 pimpl 习语 不能      更新时间:2023-10-16

我在封装令牌向量的 TokenList 类上使用我的 Push 函数时遇到问题。每当我调用 Push 函数时,即使我正确初始化了 Token 变量,Token 类中的成员变量 word 也是空的。我也尝试使用整数,它存储垃圾数。

令牌类

class Token {
private:
    class Impl;
    std::unique_ptr<Impl> impl;
public:
    Token();
    Token(const Token& token);
    Token(const std::string& word);
    ~Token();
    std::string GetWord();
    void SetWord(const std::string& word);
};

令牌列表类

class TokenList {
private:
    class Impl;
    std::unique_ptr<Impl> impl;
public:
    TokenList();
    TokenList(const TokenList& tokenList);
    ~TokenList();
    std::size_t Size() const;
    void Push(const Token& token);
    Token& operator[](int i);
    const Token& operator[](int i) const;
};

实现

class TokenList::Impl {
private:
    std::vector<Token> tokens;
public:
/* .... */
    void push(const Token& token) {
        tokens.push_back(token);
    }
};
void TokenList::Push(const Token& token) { impl->push(token); }

主要

TokenList tokens;
Token s1 ("hello");
Token s2 ("world");
tokens.Push(s1);
tokens.Push(s2);
for (int i = 0; i < tokens.Size(); ++i)
   cout << i << ": " << tokens[i].GetWord() << endl;

这是我运行 main 时的输出:

0:
1:

我尝试使用字符串而不是 TokenList 作为矢量的类型参数,它运行良好。当我跟踪问题时,它是在推送函数中没有获得正确传递的令牌值。那么是什么原因导致 TokenList 的推送函数不采用 Token 类的成员值呢?

我已经

实现了所有丢失的代码,但我无法重现您的问题。请注意,我添加了一个复制赋值运算符,因为对于存储在不可移动的向量中的类型,这是必需的。我已经发布了下面的代码,以便您可以与您的实现进行比较。(这使用了一些C++11功能)

#include <string>
#include <vector>
#include <iostream>
#include <memory>

class Token {
private:
    struct Impl;
    std::unique_ptr<Impl> impl;
public:
    Token();
    Token(const Token& token);
    Token(const std::string& word);
    Token& operator=(const Token& token);
    std::string GetWord();
    void SetWord(const std::string& word);
};
class TokenList {
private:
    struct Impl;
    std::unique_ptr<Impl> impl;
public:
    TokenList();
    TokenList(const TokenList& tokenList);
    std::size_t Size() const;
    void Push(const Token& token);
    Token& operator[](int i);
    const Token& operator[](int i) const;
};
// Token Implementation
struct Token::Impl
{
    std::string Word;
};
Token::Token() : impl{ std::make_unique<Impl>() }
{
}
Token::Token(const Token& token) : Token{}
{
    impl->Word = token.impl->Word;
}
Token::Token(const std::string& word) : Token{}
{
    impl->Word = word;
}
Token& Token::operator=(const Token& token)
{
    impl->Word = token.impl->Word;
    return *this;
}
std::string Token::GetWord()
{
    return impl->Word;
}
void Token::SetWord(const std::string& word)
{
    impl->Word = word;
}
// TokenList Implementation
struct TokenList::Impl 
{
    std::vector<Token> tokens;
    void push(const Token& token) 
    {
        tokens.push_back(token);
    }
};
TokenList::TokenList() : impl{ std::make_unique<Impl>() }
{
}
TokenList::TokenList(const TokenList& tokenList) : TokenList{}
{
    impl->tokens = tokenList.impl->tokens;
}
void TokenList::Push(const Token& token)
{ 
    impl->push(token); 
}
std::size_t TokenList::Size() const
{
    return impl->tokens.size();
}
Token& TokenList::operator[](int i)
{
    return impl->tokens[i];
}
const Token& TokenList::operator[](int i) const
{
    return impl->tokens[i];
}
int main()
{
    TokenList tokens;
    Token s1("hello");
    Token s2("world");
    tokens.Push(s1);
    tokens.Push(s2);
    for (int i = 0; i < tokens.Size(); ++i)
        std::cout << i << ": " << tokens[i].GetWord() << std::endl;
}