假设我想根据特定情况实例化不同类型的对象,所以我会在if语句的主体内实例化它们。问题是如果您想稍后使用该对象,则需要在实例化之前声明它。如何声明一个通用对象。是否有类似Java中的对象类?
我做了一些谷歌搜索,如“通用对象c ++”和“对象类c ++”,似乎没有类似的东西。
答案 0 :(得分:4)
这个问题可以用接口来解决。现在,C ++不知道接口,但您可以轻松地使用抽象基类做类似的事情:
class Base { ... }
class A : public Base { ... } // A is a Base
class B : public Base { ... } // B is a Base
...
Base *X; // that's what you will end up using
if (some_condition)
X = new A(); // valid, since A is a Base
else
X = new B(); // equally valid, since B is a Base
这将要求您将常用功能放入基类中,以便您可以在X
上实际执行操作。
(如果你从Base
之类的东西派生出你的所有类,你最终会得到像C#或Java那样的超类。但是,在我看来,通用编程,即模板在C ++中,大大减少了对类似超类的需求。我敢打赌,在大多数情况下,你将能够找到更好的代码设计。)
答案 1 :(得分:3)
与Java不同,C ++没有所有类继承的“母”对象。为了完成你所说的,你需要使用你自己的类层次结构的基指针。
Animal* a;
if (...) a = new Cat();
else if (...) a = new Dog();
另外,因为没有垃圾收集,所以当你做这类事情时最好使用智能指针。否则,请务必记得delete a
。您还需要确保Animal
有virtual destructor。
答案 2 :(得分:2)
C ++中没有“所有类的祖先”。但是有一些选择可以做类似的事情。
正如stakx建议的那样,如果可能的话,建立一个基类。从面向对象的设计角度来看,这是最好的。是否存在要应用于所有对象的常见操作?如果是这样,请尝试编写接口,并使接口成为基类。或者,您可以使用模板来获取编译时多态性,而不是运行时多态性。
如果这太难了,那么看一下像boost::any
这样的包装类。这可以保存任何(可复制)类型。它是一个不透明的包装器,您必须知道放入其中的完全类型的数据,才能将其取回。例如,如果您输入Derived *
,则需要使用boost::any_cast<Derived *>(wrapped)
来获取数据 - boost::any_cast<Base *>(wrapped)
将无效。
答案 3 :(得分:1)
std::shared_ptr<Base> X( some_condition ? new A() : new B() );
答案 4 :(得分:1)
堆解决方案昂贵且容易出错。对于没有构造堆分配的太重的对象,以下方法是可取的:
Derived1 d1;
Derived2 d2;
Base * b = 0;
if (useD1) {
b = &d1;
} else {
b = &d2;
}
这里我们分配我们在堆栈上可能需要的两种类型。没有堆分配,没有删除操作符,没有智能指针。唯一的问题 - 不能扩展到要预先分配的复杂类。
答案 5 :(得分:0)
C ++中没有通用的基类,所以如果你是这些类的作者,你应该自己定义这样的共同祖先,或者你可以使用void *虽然我不推荐后者。
如果您无法修改类,那么您可以引入实现所需接口的包装器,如下所示:
class A {};
class B {};
class MyBase
{
// Define the interface that you need.
};
class MyA : public MyBase
{
private:
A a;
public:
// Implement MyBase in terms of A.
};
class MyB : public MyBase
{
private:
B b;
public:
// Implement MyBase in terms of B.
};
int main ()
{
MyBase* base = 0;
if (useA)
base = new MyA();
else
base = new MyB();
}