提供纯虚函数的定义

时间:2015-06-10 04:30:10

标签: c++ virtual

我是一名Java程序员,并且对于为纯虚函数提供定义这一事实感到很担心。在Java中,我习惯于将抽象方法视为方法,我们将在基类中提供deifinitions。但以下代码完全有效:

#include <iostream>

struct A
{
   virtual ~A() = 0;
};

A::~A(){ std::cout << "~A()" << std::endl; }

struct B : A
{
    ~B(){ std::cout << "~B()" << std::endl; }
};

A *a = new B;


int main()
{
    delete a;
}

但如果我们尝试做类似的事情:

#include <iostream>

struct A
{
   virtual ~A() = 0;
   virtual void foo() = 0;
};

void A::foo(){ }
A::~A(){ std::cout << "~A()" << std::endl; }

struct B : A
{
    ~B(){ std::cout << "~B()" << std::endl; }
};

A *a = new B;


int main()
{
    delete a;
}

编译器会抱怨没有提供纯虚函数的定义。为什么我们可以在namesapace范围中定义纯虚拟析构函数,但不能为通常的成员函数执行此操作。

这是一个例外而非规则吗?

3 个答案:

答案 0 :(得分:4)

您可以定义任何纯虚拟成员函数。但是,即使您定义A::foo,它仍然是纯粹的,因此AB仍然是抽象类,可能无法实例化。这将是编译器可能发出的任何错误的原因。

答案 1 :(得分:2)

您显然对第二版代码中出错的原因感到困惑。

在命名空间范围内为纯虚函数,任何纯虚函数提供定义没有任何问题。无论是析构函数还是常规函数都无关紧要。没有编译器会抱怨这一点。

您在代码的第二个版本中提供的A::foo的定义完全合法,并且不会引起编译器的抱怨。第二个代码的唯一问题是B不会覆盖foo。因此B仍然是一个抽象类。而你正在尝试实例化它。

在代码的第一个版本中,从B继承的唯一纯函数A是析构函数,而B中提供了析构函数的非纯函数定义。所以,B不再是抽象类,可以合法地实例化。

在代码B的第二个版本中,继承了A的两个纯虚函数 - 析构函数和foo。由于您没有覆盖foo中的BB仍然是一个抽象类,无法实例化。

这就是它的全部。该错误与在命名空间范围内为纯虚函数提供正文的能力无关。

答案 2 :(得分:1)

当我使用g ++ 4.8.2编译上述程序时,我收到以下消息:

编译器命令:

{
  "rules": {
    "roles":{
      ".read": "root.child('roles').child(auth.uid).child('role').val() === 'admin'",
      ".write": "root.child('roles').child(auth.uid).child('role').val() === 'admin'",
      "$id" : {
        ".read" : "$id === auth.uid"
      }
    },
    "users": {
      ".read" :  "root.child('roles').child(auth.uid).child('role').val() === 'admin'",
      "$user":{        
        ".read": "$user === auth.uid",
        ".write": "$user === auth.uid"
      }
    }
  }
}

错误讯息:

g++ -Wall -std=c++11     socc.cc   -o socc

错误消息的要点是socc.cc:17:12: error: cannot allocate an object of abstract type ‘B’ A *a = new B; ^ socc.cc:12:8: note: because the following virtual functions are pure within ‘B’: struct B : A ^ socc.cc:9:6: note: virtual void A::foo() void A::foo(){ } ^ make: *** [socc] Error 1 是一种抽象类型,因为它不提供覆盖的B,它在基类中被声明为纯虚函数。

void foo();的定义并非违法。以下程序运行正常:

A::foo()
相关问题