c++ 您能使用pimpl习惯用法在一个类中跨多个cpp文件使用吗?

70gysomp  于 2022-12-30  发布在  其他
关注(0)|答案(2)|浏览(119)

例如,我的意思是这样的,假设你有一个头文件和一个pimpl类,你可以跨两个cpp文件定义这个类的函数,而不用重新定义这个类的变量吗?
在使用静态变量作为指针和在两个文件中重定义之前,我已经尝试过这种方法,但是,当在文件之间移动时,我总是遇到类变量被擦除的问题。

//Header
class PRIVATE {
  struct Test2;

public:
  struct Test;

  std::shared_ptr<Test> Client_ptr;

  PRIVATE();

}; //PRIVATE

static std::shared_ptr<PRIVATE> PB = std::shared_ptr<PRIVATE>();
//Cpp1
//Implementation for Private
//Implementation for Test1

//Function not inside either class, references PB, defined in Cpp2  -> READ ACCESS VIOLATION
//Cpp2
//Definition Goes Here
//Implementation for Test2

//Function not inside either class, references PB, defined in Cpp1  -> READ ACCESS VIOLATION
ivqmmu1c

ivqmmu1c1#

通常对于这类事情,你会有一个公共头,例如。

#pragma once
class Foo {
    Foo();
    ~Foo();

private:
  struct FooPimpl;
  FooPimpl* pimpl;
};

然后你会有第二个私有头文件(通常在你的源目录下,而不是include dir),私有头文件将定义你的Pimpl结构类型。

#pragma once

struct Foo::FooPimpl {
  /*stuff*/
};

你需要在某处声明你的ctors / dtors,例如。
Foo.cpp

#include "public/Foo.h"
#include "./Foo.h"

Foo::Foo() {
    pimpl = new FooPimpl;
}
Foo::~Foo() {
    delete pimpl;
}

您可以对所有其他源文件使用相同的模式(例如,先包含公共头文件,然后包含私有头文件)。

olmpazwi

olmpazwi2#

将pimpl内部构件拆分到单独的编译单元的一个问题是,您需要至少一个知道如何销毁所有成员的编译单元。
例如:

//main.h
class Main {
  struct Test;
  struct Test2;
  std::unique_ptr<Test> pimpl1;
  std::unique_ptr<Test2> pimpl2;
public:
  Main();
  ~Main();
};

//test1.cpp
struct Main::Test {
};
// we don't know what Test2 is, so we cannot define Main::~Main().

//test2.cpp
struct Main::Test2 {
};
// we don't know what Test is, so we cannot define Main::~Main().

一种解决方案是:

class Main {
  struct Test;
  struct Test2;
  std::unique_ptr<Test> pimpl1;
  struct Defer {
    std::unique_ptr<Test2> pimpl2;
    Defer();
    ~Defer();
  };
  Defer defer;
public:
  Main();
  ~Main();
};

现在,Main::Defer::~Defer()可以存在于test2.cpp中,它知道如何销毁其pimpl2示例,但不需要知道如何销毁pimpl.类似地,由于Main::Defer是在main. h中定义的(而不仅仅是声明的),Main::~Main()可以正确地销毁其defer成员:

//test1.cpp
/* Test definition */
Main::Main() : pimpl(std::make_unique<Test>()), defer() {}
Main::~Main() {}

//test2.cpp
/* Test2 definition */
Main::Defer::Defer() : pimpl2(std::make_unique<Test2>()) {}
Main::Defer::~Defer() {}

TestTest2相互通信仍然很困难,但这正是pimpl的要点,可以通过Main提供一些接口或通过一些声明一些接口的中间头来简化。

相关问题