我的问题陈述如下.存在"域"的概念,其由许多"子域"组成.现在,这些子域本身就是域.以下是我可以做的事情的基本方法.我可以使用auto_ptr或其他东西,但现在暂时离开.
class Domain
{
private:
Domain* subdomains;
}
Run Code Online (Sandbox Code Playgroud)
但是,我能够编译并运行以下程序,我认为它做了同样的事情并给了我想要的东西.
#include <iostream>
#include <vector>
#include <string>
class Domain
{
private:
std::string name_;
public:
std::vector<Domain> subdomains;
Domain(std::string name) : name_(name) {};
std::string name() {return name_;}
void addSubDomain(std::string subDomainName);
};
void Domain::addSubDomain(std::string subDomainName)
{
subdomain.push_back(Domain(subDomainName));
}
int main()
{
std::cout<<"Hello, World"<<std::endl;
Domain domain("wow");
domain.addSubDomain("wow-child");
std::cout<<"Domain name is "<<domain.name()<<std::endl;
std::cout<<"Subdomain name is "<<domain.subdomain[0].name()<<std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我运行它的输出是
$./main
Hello, World
Domain name is wow
Subdomain name is wow-child
Run Code Online (Sandbox Code Playgroud)
我的问题是,在实施以下内容时,我是否有任何陷阱?现在,我看不到任何东西.如果没有陷阱,那么这对我的问题来说是一个非常好的解决方案.
编辑
如果这不是一个解决方案,那么还有另一个我可以使用的解决方案,它不涉及原始指针的管理吗?
当您将 a 用于unique_ptr<T>前向声明的类型时T,unique_ptr析构函数要求 theT是完整的,但还需要移动赋值运算符(和reset),根据此表:
因此,对于您的pImpl习惯用法,要正确实现它,您必须声明 thedelete和 the move assignment method(这作为副作用,将它们标记为非内联):
class impl_t;
class A
{
std::unique_ptr<impl_t> p_impl;
public:
// Implement in A.cpp as A::~A() = default;
~A();
// Implemented in A.cpp as A& operator=(A&&) = default;
A& operator=(A&& he);
};
Run Code Online (Sandbox Code Playgroud)
但是,由于std::unique_ptr是动态内存的 RAII 解决方案,并且您pImpl已经在一个类中,并且无论如何您都被迫编写析构函数,因此管理原始指针不是更好吗,因为您的类已经是 RAII-就像从 ? 的角度来看p_impl:
class impl_t;
class A
{
impl_t* p_impl;
public:
~A(); // The destructor …Run Code Online (Sandbox Code Playgroud) 我无法理解以下情况.它是关于使用基于std::unique_ptr派生类的pimpl习语.给定一个简单的类层次结构声明如下:
class Foo
{
public:
virtual ~Foo();
//...
};
struct X;
class Bar : public Foo
{
public:
~Bar();
//...
private:
std::unique_ptr<X> _d;
};
Run Code Online (Sandbox Code Playgroud)
我只显示与我的问题相关的代码.
想象一下,类Foo是一些接口,而类'Bar'是实现它的.我想用pimpl成语Bar.析构函数是虚拟的,并在相应的cpp文件中定义.此外struct X,只有前向声明的完整定义可以在cpp中访问,因此可以实例化析构函数的Bar析构函数std::unique_ptr<X>::~unique_ptr().当我尝试创建一个实例时Bar,我希望它能够工作
int main()
{
Bar b;
}
Run Code Online (Sandbox Code Playgroud)
相反,我得到编译错误使用未定义类型'X'后跟消息无法删除不完整类型(在Visual Studio 2013 Update 2中).但是,如果我显式添加默认构造函数Bar,则main()正确编译/构建.
class Foo
{
public:
virtual ~Foo();
};
struct X;
class Bar : public Foo
{
public:
Bar();
~Bar();
private:
std::unique_ptr<X> …Run Code Online (Sandbox Code Playgroud) 在我的GUI系统中,主要构建块是Container类,可以绘制(=可绘制).然而,Container它本身就是一种" 一种表 " - 它包含细胞.
Cellclass用于布局.容器具有的单元格数由行数和列数定义.Cell对象不可见.
这就是问题所在.Cell无法绘制Container对象- 它们包含对象,这些Cell对象在调用时由对象中定义的规则(对齐,填充等)绘制cell.draw().
我知道这可以通过使用原始指针来避免在这里创建的循环依赖关系轻松解决,但我想使用智能指针,如果可能的话.但是,根据我得到的错误,显然智能指针必须知道对象的大小,不像原始指针.
Unique_ptr错误
/usr/include/c++/4.8/bits/unique_ptr.h:65:22: error: invalid application of ‘sizeof’ to incomplete type ‘Container’
static_assert(sizeof(_Tp)>0,
Run Code Online (Sandbox Code Playgroud)
Container.hpp
#include <Cell.hpp> // Causes circular dependency
class Cell; // Causes error: invalid application of ‘sizeof’
class Container
{
// ...
private:
std::vector<std::unique_ptr<Cell>> cells;
// ...
}
Run Code Online (Sandbox Code Playgroud)
Cell.hpp
#include <Container.hpp> //Causes circular dependency
class Container; // Causes error: …Run Code Online (Sandbox Code Playgroud) 我已经查看了许多关于 pImpl、unique_ptr 和前向声明的 SO 问题,但无法找出问题所在。答案是std::unique_ptr<T> 需要知道 T 的完整定义吗?看起来很完整,但我不知道如何将其应用到我的情况。
我在https://wandbox.org/permlink/9joq3PnkEZ6j8TI8有一个简单的 pImpl 模式。主类包含 impl 类的 unique_ptr,它管理一些资源,因此它具有自定义构造函数/析构函数。我正在使用带有 clang 14 的 C++20(在 MacOS 上,确实如此,但在上面的 wandbox 中也发生了同样的错误)。
编译它会出现可怕的“对不完整类型无效应用‘sizeof’”错误。
代码是这样的:
// testclass.h
#include <experimental/propagate_const>
// Main class with a pImpl pattern -- impl class is incomplete here.
class Main {
public:
void main_f();
Main();
private:
class impl;
std::experimental::propagate_const<std::unique_ptr<impl>> pImpl;
};
Run Code Online (Sandbox Code Playgroud)
// testclass.cpp
#include "testclass.h"
// Implementation of Main with its impl
class Main::impl {
private:
int foo;
public:
impl() = default;
~impl() { …Run Code Online (Sandbox Code Playgroud) c++ ×5
pimpl-idiom ×2
c++11 ×1
containment ×1
nested-class ×1
raii ×1
raw-pointer ×1
stdvector ×1
unique-ptr ×1