首先,我是 C++ 新手,尤其是以 OOP 方式使用 C++。我有一个有多个子类的类,我想知道我是否可以含糊地声明一个变量来接受一个对象,而不限制哪些对象可以存储在其中。我问是因为多个孩子中的一个最终会被一次使用。因此,如果我不能模棱两可地声明一个变量,我可以通过一种方法来确定正在使用的众多变量中的哪一个。
类似的东西
obj randomObj = new className;
代替
className randomObj = new className
由于所有类都派生自一个公共基类,因此您可以将变量声明为该基类类型,但仍然可以将任何派生类分配给它,例如:
class BaseClass
{
...
};
class DerivedClass : public BaseClass
{
...
};
BaseClass *randomObj = new DerivedClass;
一个容器只能包含相同类型的对象。如果你想要一个异构集合,你需要在容器中插入一个“句柄”类型并间接访问对象。标准句柄类型是指针,标准构造是std::vector<std::unique_ptr<Base>>
,像这样:
#include <memory>
#include <utility>
#include <vector>
template <typename T, typename ...Args>
std::unique_ptr<T> make_unique(Args &&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); // or "::new"
}
struct Base
{
virtual ~Base() { }
};
struct Derived1 : Base { /* ... */ };
struct Derived2 : Base { /* ... */ };
struct Derived3 : Base { /* ... */ };
std::vector<std::unique_ptr<Base>> v;
用法:
v.push_back(make_unique<Derived1>(true, 'a'));
v.push_back(make_unique<Derived2>(11, 22, 33));
v.push_back(make_unique<Derived3>("hello", "world"));
您说您是 C++ 新手,而您用来描述所需内容的语法表明您更熟悉其他语言,例如 Java 或 C#。您显示的语法在这些语言中运行良好:
Foo myFoo = new DerivedFoo;
这是因为,在 Java 和 C# 的幕后myFoo
实际上表现为指向 Foo 的指针,而不是能够存储 Foo 的固定内存区域的名称。在 C++ 中,语法Foo myFoo
创建了这样一个固定的内存区域。即使您尝试通过这样做将一些派生类型放在那里:
DerivedFoo myDerivedFoo;
Foo myFoo = myDerivedFoo;
myFoo
仍然只能持有一个 Foo 对象。在 Foo 的初始化过程中,所有不是 Foo 的东西都会被“切掉” myFoo
,因为它不适合那个固定的内存区域。
因此,在 C++ 中,您必须使用 C++ 的指针语法显式地执行 Java 和 C# 在幕后所做的事情:
Foo *myFoo = new DerivedFoo;
NowmyFoo
是一个指向 Foo 的指针,该指针可以引用任何Foo
对象,包括 DerivedFoo 的 Foo 部分,而无需任何切片或任何事情发生。new DerivedFoo
创建一个 DerivedFoo 可以存在的内存区域,然后myFoo
设置为指向Foo
created 的部分DerivedFoo
。