C++ 如何正确地实现C+中仅由抽象库知道的对象列表的创建(和分配)+;?
。(-但同时,)或(尽管) 我仔细阅读了所有这些,现在我觉得我知道的比以前少了。我一点也不知道如何编写一个代码,在我看来,这个代码应该是微不足道的,同时尊重所有这些精心编写和深思熟虑的答案中提到的最佳实践 下面是我想要实现的。(我不假装它是正确的C++,但我只是想传达这个想法)。C++ 如何正确地实现C+中仅由抽象库知道的对象列表的创建(和分配)+;?,c++,C++,。(-但同时,)或(尽管) 我仔细阅读了所有这些,现在我觉得我知道的比以前少了。我一点也不知道如何编写一个代码,在我看来,这个代码应该是微不足道的,同时尊重所有这些精心编写和深思熟虑的答案中提到的最佳实践 下面是我想要实现的。(我不假装它是正确的C++,但我只是想传达这个想法)。 //这东西纯粹是虚拟的! 类BaseStuff{} //具有不应分割的重要行为和数据成员 类SomeStuff:public BaseStuff{} //请不要把我切成片 类OtherStuff:public Base
//这东西纯粹是虚拟的!
类BaseStuff{}
//具有不应分割的重要行为和数据成员
类SomeStuff:public BaseStuff{}
//请不要把我切成片
类OtherStuff:public BaseStuff{}
BaseStuff CreateStuff()
{
//落下一组规则,根据月亮的相位创建SomeStuff或OtherStuff实例
}
std::vector CreateListOfStuff()
{
//我经常打电话给你
}
公共静态void main()
{
列出AllTheStaff=CreateListOfStuff();
//用东西处理事情
}
如果想要多态性,必须使用指针
BaseStuff* CreateStuff()
{
...
}
List<BaseStuff*> allTheStuff = CreateListOfStuff();
BaseStuff*CreateStuff()
{
...
}
列出AllTheStaff=CreateListOfStuff();
实际上,如果可能的话,您应该更喜欢堆栈分配而不是堆分配。但这并不总是可能的
当然,代替原本不安全的原始指针,您可以考虑使用智能指针等,但智能指针仍然是
List<shared_ptr<BaseStuff>> = CreateListOfStuff
List=CreateListOfStuff
您将存储指向实际指向派生类型的基类的多态指针(注意我在这里使用了std::unique\u ptr
s):
#包括
#包括
#包括
阶级基础
{
公众:
虚空呼喊()=0;
};
类子:公共基
{
公众:
void shout(){std::cout在这种情况下,您经常(通常?)做的一件事是在基类中定义一个成员函数(传统上称为clone
),以创建对象的副本:
class BaseStuff {
public:
virtual BaseStuff *clone() const = 0;
};
class SomeStuff : public BaseStuff {
virtual void SomeStuff *clone() const {
return new SomeStuff(*this); // needs a correctly functioning copy ctor
}
};
class OtherStuff : public BaseStuff {
public:
virtual OtherStuff *clone() const {
return new OtherStuff(*this);
}
};
这使我们可以通过指向底部的指针复制项目,而无需切片。通过这种方式,如果您希望(例如)您的listofsuff
存储您放入其中的项目的副本(而不仅仅是指向原始项目的指针,原始项目可能不再存在,留下悬空指针),您可以添加类似以下内容的项目:
class ListOfStuff {
class Node {
// Note: this is extremely incomplete. Almost certainly needs a dtor,
// and you want to either implement or delete the copy ctor to either
// do copying correctly, or assure it can't happen at all.
Node *next;
BaseStuff *data;
public:
Node(BaseStuff *data, Node *next = nullptr) : data(data), next(next) {}
};
Node *begin, *end;
public:
Add(BaseStuff *item) {
BaseStuff *new_item = item->clone();
end->next = new node(new_item);
end = end->next;
}
};
只要稍加修改,我就同意Armen Tsirunyan的基本观点:当处理多态层次结构时,通常必须通过指针或(修改)引用来完成
在许多情况下,您可以使用智能指针而不是指针——但不是在所有情况下都可以,并且为特定情况选择正确的智能指针本身就非常重要。不过,您通常希望在指针周围使用某种包装器——上面的代码避免使用它们,主要是因为我不太了解您要选择什么他纠正了一个。所有的新的和删除有什么区别?@golergka:这可以处理我的智能指针。请参阅编辑。我会更进一步,将CreateStuff()
的返回类型更改为智能指针。@golergka:你仍然必须使用新的(除非你改用使你共享()
),但智能指针的全部目的是为您自动调用delete
。您应该尽可能避免直接调用new
和delete
,让框架来为您处理。感谢您的帮助。但我想要实现的仍然不起作用:@golergka您无法创建std::vector
的const std::unique_ptr
。此外,返回值上的const
是愚蠢的(如果不是完全无用的话)。只需将变量本身设置为const
。请参见。谢谢!但我不应该将所有内容默认设置为不可变吗?@golergka它不会产生任何效果;任何人都可以将函数的const
返回值复制到非const
变量中。这就是为什么您需要将变量本身设置为const
,然后离开函数没有。@golergka好吧,语言中有很多东西,它有它的“用途”。关于引用,你是对的,但是指针有着与,比如说,int
,相同的“问题”,因为你只需将一个副本复制到一个非常量
变量中。要了解更多的背景信息,请跟随重复的字符串
class BaseStuff {
public:
virtual BaseStuff *clone() const = 0;
};
class SomeStuff : public BaseStuff {
virtual void SomeStuff *clone() const {
return new SomeStuff(*this); // needs a correctly functioning copy ctor
}
};
class OtherStuff : public BaseStuff {
public:
virtual OtherStuff *clone() const {
return new OtherStuff(*this);
}
};
class ListOfStuff {
class Node {
// Note: this is extremely incomplete. Almost certainly needs a dtor,
// and you want to either implement or delete the copy ctor to either
// do copying correctly, or assure it can't happen at all.
Node *next;
BaseStuff *data;
public:
Node(BaseStuff *data, Node *next = nullptr) : data(data), next(next) {}
};
Node *begin, *end;
public:
Add(BaseStuff *item) {
BaseStuff *new_item = item->clone();
end->next = new node(new_item);
end = end->next;
}
};