我的问题陈述如下。存在“域”的概念,其由许多“子域”组成。现在,这些子域本身就是域名。以下是我可以做的事情的基本方法。我可以使用auto_ptr或其他东西,但现在暂时离开。
class Domain
{
private:
Domain* subdomains;
}
然而,我能够编译并运行以下程序,我认为它做了同样的事情并给了我想要的东西。
#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;
}
我运行它的输出是
$./main
Hello, World
Domain name is wow
Subdomain name is wow-child
我的问题是,在实施以下内容时,我是否有任何陷阱?现在,我看不到任何东西。如果没有陷阱,那么这对我的问题来说是一个非常好的解决方案。
修改
如果这不是一个解决方案,那么我可以使用另一个不涉及原始指针管理的解决方案吗?
答案 0 :(得分:6)
这是未定义的行为,因为在您定义成员时,该类尚未完全定义。此时,std::vector<Domain>
需要实例化,从模板std::vector<T>
到类std::vector<Domain>
(以确定其大小等)。当实例化发生时,标准要求完全定义类。
答案 1 :(得分:2)
正如约翰内斯正确指出的那样,你的程序是未定义的。但是,如果这样做,你的程序将完全有效:
class Domain {
…
std::vector<Domain*> subdomains;
…
};
当然,你必须管理指针。 (例外安全,RAII,三规则等等)。
答案 2 :(得分:0)
从stackoverflow中读取其他答案和许多其他问题后。我想用自己的话总结答案。尽管约翰内斯已正确回答了这个问题,但我还想补充一点。所以,就是这样。
由于Johannes的回答所给出的理由,在所有类型的用法中,问题中给出的代码的行为在C ++ 03中是未定义的。但是,在C ++ 11标准中,要求已经改变。除非该类特别允许,否则行为仍未定义。
C ++ 11 $ 17.6.4.8其他函数(...)2。在下列情况下效果未定义:( ...)特别是 - 如果使用不完整类型(3.9)作为模板参数实例化模板组件,除非特别允许该组件。
当前的例子是有效的,因为std :: vector的特定实现不包含T类型的任何属性,只包含T *类型的属性。因此,这是一个幸运编译的案例,根据容器的不同,可能会或可能不会一直有效。
问题的解决方案是当前使用Boost :: Containers specifically support the incomplete types。
如果需要,std :: unique_ptr和std :: shared_ptr指针可用作管理原始指针模型的替代品,只需很少捕获。这个问题的答案是here。人们可以看到详细的解释here。因此,如果需要一个std :: container,那么他可以使用上面的指针使用指针容器。但是,必须满足一些条件。这些条件在上面给出的链接中描述。
总而言之,现在最好的方法是使用boost :: containers。但是,他们引入了对boost的依赖。如果你想避免依赖,那么你可以使用std :: unique_ptr和std :: shared_ptr。但是,在可以做什么方面存在一些条件和限制。
boost :: shared_ptr也允许使用不完整的类型。但是,这也有一些局限性。