4

考虑以下 :

class Abstract
{
public:
    virtual void func() = 0;
};

int main() {

    Abstract abs1; // doesn't compile
    Abstract * abs2 = new Abstract(); // doesn't compile
    Abstract * abs3;  // compiles

    return 0;
}

请注意我没有实现func(),那么为什么可以Abstract * abs3; 在我们有纯虚方法和抽象类的地方做呢?我知道如果我尝试执行 abs3->func(); 会出现运行时错误;,但是,我仍然不清楚为什么 C++ 允许编译该代码......?

谢谢,罗恩

4

6 回答 6

7

abs3是指向类的指针。它可以安全地初始化为 Abstract 的任何具体子类或 NULL。编译器必须允许这样做,因为虽然您不能创建抽象类,但您必须能够创建指向它们的指针。请参阅下面的示例

class Concrete: public Abstract
{
public:
    virtual void func() { // do something };
};


int main ()
{
   Abstract* abs3 = NULL;
   abs3 = new Concrete;
}
于 2011-09-01T10:53:39.333 回答
4

你不能实例化一个抽象类,但是有一个指向它的指针是完全可以的。这实际上在 OO 设计中经常使用。

于 2011-09-01T10:44:55.677 回答
3

简答

编译器不会发出任何错误,因为创建指向抽象类的指针非常好。

长答案

除非,为了实例化一个类并创建一个类型的对象,编译器需要知道该类型的组成。

您可以创建指向抽象类的指针,因为系统上的所有指针都具有相同的大小,无论它们指向的类型如何。
请注意,创建指针不会调用构造函数。

您不能创建抽象类的对象,因为该类有一些未完全定义的方法,因此编译器不知道该类的组成。因此,禁止它的实例化。

编辑:
即使您为纯虚函数提供定义(并且这样做完全有效)您仍然无法实例化抽象类,因为当您将函数声明为纯虚拟时,编译器会将类视为抽象(不完整)并且它不能再被实例化了。

于 2011-09-01T10:44:11.163 回答
1

实际上,能够创建指向抽象类的指针的关键在于将其指向派生自抽象类的(具体)类:

class Abstract
{
public:
    virtual void func() = 0;
};

class Derived1 : public Abstract
{
public:
    virtual void func() { /* do something */ }
}

class Derived2 : public Abstract
{
public:
    virtual void func() { /* do something else */ }
}

然后,例如:

Abstract * ap;

if (/*something*/)
    ap = new Derived1();
else
    ap = new Derived2();

ap->func();
delete ap;
于 2011-09-01T10:52:12.423 回答
1

继承是您缺少的关键思想。如果Vehicle是抽象的,并且 aCar是车辆,那么Vehicle*对于指向实例化的指针来说,它是一个完全有效的类型Car。抽象基类是作为方法参数的有效类型(引用),无论传递的是aCar还是 a ,都会调用正确的虚实现。这是语言的一个关键特征。Bikefunc

于 2011-09-01T10:53:13.400 回答
0

您根本不能拥有一个未实现一个或多个方法的类的实例。

您在这里尝试做的是拥有一个具有名为 的纯抽象方法的类的实例func():这是不可能的。

Abstract * abs3

编译为一个未初始化的指针,你没有分配任何Abstract.

Abstract abs1;
Abstract * abs2 = new Abstract();

永远不会编译。您应该指定Abstract(通过继承)提供一个实现,func()并且此时您将能够拥有此类派生类的实例。

于 2011-09-01T11:53:32.933 回答